http://linux-sound.bkbits.net/linux-sound
perex@suse.cz|ChangeSet|20040623180456|17439 perex

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/06/24 17:57:53-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# sound/pci/nm256/nm256.c
#   2004/06/24 17:57:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/pci_ids.h
#   2004/06/24 17:57:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/23 11:50:26-07:00 akpm@bix.(none) 
#   Merge http://linux-sound.bkbits.net/linux-sound
#   into bix.(none):/usr/src/bk-alsa
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/06/23 11:50:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# sound/core/seq/seq_clientmgr.c
#   2004/06/23 11:50:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/sound/vx_core.h
#   2004/06/23 11:50:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/sound/seq_kernel.h
#   2004/06/23 11:50:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/sound/core.h
#   2004/06/23 11:50:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/23 20:04:56+02:00 perex@suse.cz 
#   ALSA CVS update
#   ALSA sequencer,Instrument layer,ISA,GUS drivers
#   Clean up Makefiles for the sequencer stuff using reverse selections.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/gus/Makefile
#   2004/06/23 11:56:55+02:00 perex@suse.cz +1 -5
#   ALSA CVS update
#   D:2004/06/23 17:56:53
#   C:ALSA sequencer,Instrument layer,ISA,GUS drivers
#   F:core/seq/Makefile:1.33->1.34 
#   F:core/seq/instr/Makefile:1.16->1.17 
#   F:isa/Kconfig:1.11->1.12 
#   F:isa/gus/Makefile:1.11->1.12 
#   L:Clean up Makefiles for the sequencer stuff using reverse selections.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/Kconfig
#   2004/06/23 11:56:55+02:00 perex@suse.cz +8 -0
#   ALSA CVS update
#   D:2004/06/23 17:56:53
#   C:ALSA sequencer,Instrument layer,ISA,GUS drivers
#   F:core/seq/Makefile:1.33->1.34 
#   F:core/seq/instr/Makefile:1.16->1.17 
#   F:isa/Kconfig:1.11->1.12 
#   F:isa/gus/Makefile:1.11->1.12 
#   L:Clean up Makefiles for the sequencer stuff using reverse selections.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/instr/Makefile
#   2004/06/23 11:56:55+02:00 perex@suse.cz +3 -31
#   ALSA CVS update
#   D:2004/06/23 17:56:53
#   C:ALSA sequencer,Instrument layer,ISA,GUS drivers
#   F:core/seq/Makefile:1.33->1.34 
#   F:core/seq/instr/Makefile:1.16->1.17 
#   F:isa/Kconfig:1.11->1.12 
#   F:isa/gus/Makefile:1.11->1.12 
#   L:Clean up Makefiles for the sequencer stuff using reverse selections.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/Makefile
#   2004/06/23 11:56:53+02:00 perex@suse.cz +5 -53
#   ALSA CVS update
#   D:2004/06/23 17:56:53
#   C:ALSA sequencer,Instrument layer,ISA,GUS drivers
#   F:core/seq/Makefile:1.33->1.34 
#   F:core/seq/instr/Makefile:1.16->1.17 
#   F:isa/Kconfig:1.11->1.12 
#   F:isa/gus/Makefile:1.11->1.12 
#   L:Clean up Makefiles for the sequencer stuff using reverse selections.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 19:52:02+02:00 perex@suse.cz 
#   ALSA CVS update
#   USB generic driver
#   new functions snd_usbmidi_input_stop() and snd_usbmidi_input_start()
#   needed by snd-usb-usx2y to be able to use usb_set_interface()
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2004/06/23 07:48:41+02:00 perex@suse.cz +39 -3
#   ALSA CVS update
#   D:2004/06/23 13:48:41
#   C:USB generic driver
#   F:usb/usbaudio.h:1.31->1.32 
#   F:usb/usbmidi.c:1.28->1.29 
#   L:new functions snd_usbmidi_input_stop() and snd_usbmidi_input_start()
#   L:needed by snd-usb-usx2y to be able to use usb_set_interface()
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.h
#   2004/06/23 07:48:41+02:00 perex@suse.cz +2 -0
#   ALSA CVS update
#   D:2004/06/23 13:48:41
#   C:USB generic driver
#   F:usb/usbaudio.h:1.31->1.32 
#   F:usb/usbmidi.c:1.28->1.29 
#   L:new functions snd_usbmidi_input_stop() and snd_usbmidi_input_start()
#   L:needed by snd-usb-usx2y to be able to use usb_set_interface()
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 15:02:18+02:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel
#   Each of snd_pcm_hw_refine_old_user() and snd_pcm_hw_params_old_user()
#   consume 856 bytes of stack and can invoke deep calls via the page allocator.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/pcm_native.c
#   2004/06/01 02:57:54+02:00 perex@suse.cz +55 -18
#   ALSA CVS update
#   D:2004/06/01 08:57:54
#   C:PCM Midlevel
#   F:core/pcm_native.c:1.91->1.92 
#   L:Each of snd_pcm_hw_refine_old_user() and snd_pcm_hw_params_old_user()
#   L:consume 856 bytes of stack and can invoke deep calls via the page allocator.
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/06/23 13:18:33+02:00 perex@suse.cz 
#   ALSA CVS update
#   CMIPCI driver
#   don't sleep in prepare callback
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/cmipci.c
#   2004/06/23 02:38:17+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/06/23 08:38:17
#   C:CMIPCI driver
#   F:pci/cmipci.c:1.66->1.67 
#   L:don't sleep in prepare callback
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 13:17:12+02:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel,ALSA<-OSS emulation,CMIPCI driver
#   reduce stack usage
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/cmipci.c
#   2004/06/22 11:18:41+02:00 perex@suse.cz +38 -21
#   ALSA CVS update
#   D:2004/06/22 17:22:34
#   C:PCM Midlevel,ALSA<-OSS emulation,CMIPCI driver
#   F:core/pcm_native.c:1.93->1.94 
#   F:core/oss/pcm_oss.c:1.69->1.70 
#   F:pci/cmipci.c:1.65->1.66 
#   L:reduce stack usage
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/pcm_native.c
#   2004/06/22 11:22:34+02:00 perex@suse.cz +36 -12
#   ALSA CVS update
#   D:2004/06/22 17:22:34
#   C:PCM Midlevel,ALSA<-OSS emulation,CMIPCI driver
#   F:core/pcm_native.c:1.93->1.94 
#   F:core/oss/pcm_oss.c:1.69->1.70 
#   F:pci/cmipci.c:1.65->1.66 
#   L:reduce stack usage
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/oss/pcm_oss.c
#   2004/06/22 11:20:43+02:00 perex@suse.cz +10 -5
#   ALSA CVS update
#   D:2004/06/22 17:22:34
#   C:PCM Midlevel,ALSA<-OSS emulation,CMIPCI driver
#   F:core/pcm_native.c:1.93->1.94 
#   F:core/oss/pcm_oss.c:1.69->1.70 
#   F:pci/cmipci.c:1.65->1.66 
#   L:reduce stack usage
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 13:15:50+02:00 perex@suse.cz 
#   ALSA CVS update
#   au88x0 driver
#   - Fixed the wrong pointer cast on 64bit architectures.
#   
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/au88x0/au88x0_a3d.c
#   2004/06/21 11:53:37+02:00 perex@suse.cz +4 -4
#   ALSA CVS update
#   D:2004/06/21 17:53:37
#   C:au88x0 driver
#   F:pci/au88x0/au88x0_a3d.c:1.3->1.4 
#   L:- Fixed the wrong pointer cast on 64bit architectures.
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:14:16+02:00 perex@suse.cz 
#   ALSA CVS update
#   EMU10K1/EMU10K2 driver
#   Merge EFX playback and capture streams to the single device (hw:0,2).
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2004/06/21 11:52:18+02:00 perex@suse.cz +272 -1
#   ALSA CVS update
#   D:2004/06/21 17:52:17
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.39->1.40 
#   F:pci/emu10k1/emu10k1.c:1.24->1.25 
#   F:pci/emu10k1/emufx.c:1.52->1.53 
#   F:pci/emu10k1/emupcm.c:1.25->1.26 
#   L:Merge EFX playback and capture streams to the single device (hw:0,2).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emufx.c
#   2004/06/21 11:52:18+02:00 perex@suse.cz +2 -308
#   ALSA CVS update
#   D:2004/06/21 17:52:17
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.39->1.40 
#   F:pci/emu10k1/emu10k1.c:1.24->1.25 
#   F:pci/emu10k1/emufx.c:1.52->1.53 
#   F:pci/emu10k1/emupcm.c:1.25->1.26 
#   L:Merge EFX playback and capture streams to the single device (hw:0,2).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emu10k1.c
#   2004/06/21 11:52:18+02:00 perex@suse.cz +0 -4
#   ALSA CVS update
#   D:2004/06/21 17:52:17
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.39->1.40 
#   F:pci/emu10k1/emu10k1.c:1.24->1.25 
#   F:pci/emu10k1/emufx.c:1.52->1.53 
#   F:pci/emu10k1/emupcm.c:1.25->1.26 
#   L:Merge EFX playback and capture streams to the single device (hw:0,2).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/emu10k1.h
#   2004/06/21 11:52:17+02:00 perex@suse.cz +9 -0
#   ALSA CVS update
#   D:2004/06/21 17:52:17
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.39->1.40 
#   F:pci/emu10k1/emu10k1.c:1.24->1.25 
#   F:pci/emu10k1/emufx.c:1.52->1.53 
#   F:pci/emu10k1/emupcm.c:1.25->1.26 
#   L:Merge EFX playback and capture streams to the single device (hw:0,2).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:12:57+02:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel,ALSA Core,RME32 driver,RME96 driver,NM256 driver
#   - Fix the mmap via io_remap_page_range() on nm256, rme32 and rme96.
#     Added SNDRV_PCM_INFO_MMAP_IOMEM to handle this case.
#   - Clean up the indirect accessing on RME32/RME96 drivers.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme96.c
#   2004/06/21 11:50:09+02:00 perex@suse.cz +14 -110
#   ALSA CVS update
#   D:2004/06/21 17:50:08
#   C:PCM Midlevel,ALSA Core,RME32 driver,RME96 driver,NM256 driver
#   F:core/pcm_native.c:1.92->1.93 
#   F:include/asound.h:1.40->1.41 
#   F:pci/rme32.c:1.33->1.34 
#   F:pci/rme96.c:1.35->1.36 
#   F:pci/nm256/nm256.c:1.38->1.39 
#   L:- Fix the mmap via io_remap_page_range() on nm256, rme32 and rme96.
#   L:  Added SNDRV_PCM_INFO_MMAP_IOMEM to handle this case.
#   L:- Clean up the indirect accessing on RME32/RME96 drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme32.c
#   2004/06/21 11:50:09+02:00 perex@suse.cz +16 -105
#   ALSA CVS update
#   D:2004/06/21 17:50:08
#   C:PCM Midlevel,ALSA Core,RME32 driver,RME96 driver,NM256 driver
#   F:core/pcm_native.c:1.92->1.93 
#   F:include/asound.h:1.40->1.41 
#   F:pci/rme32.c:1.33->1.34 
#   F:pci/rme96.c:1.35->1.36 
#   F:pci/nm256/nm256.c:1.38->1.39 
#   L:- Fix the mmap via io_remap_page_range() on nm256, rme32 and rme96.
#   L:  Added SNDRV_PCM_INFO_MMAP_IOMEM to handle this case.
#   L:- Clean up the indirect accessing on RME32/RME96 drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/nm256/nm256.c
#   2004/06/21 11:50:09+02:00 perex@suse.cz +6 -10
#   ALSA CVS update
#   D:2004/06/21 17:50:08
#   C:PCM Midlevel,ALSA Core,RME32 driver,RME96 driver,NM256 driver
#   F:core/pcm_native.c:1.92->1.93 
#   F:include/asound.h:1.40->1.41 
#   F:pci/rme32.c:1.33->1.34 
#   F:pci/rme96.c:1.35->1.36 
#   F:pci/nm256/nm256.c:1.38->1.39 
#   L:- Fix the mmap via io_remap_page_range() on nm256, rme32 and rme96.
#   L:  Added SNDRV_PCM_INFO_MMAP_IOMEM to handle this case.
#   L:- Clean up the indirect accessing on RME32/RME96 drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2004/06/21 11:50:08+02:00 perex@suse.cz +14 -0
#   ALSA CVS update
#   D:2004/06/21 17:50:08
#   C:PCM Midlevel,ALSA Core,RME32 driver,RME96 driver,NM256 driver
#   F:core/pcm_native.c:1.92->1.93 
#   F:include/asound.h:1.40->1.41 
#   F:pci/rme32.c:1.33->1.34 
#   F:pci/rme96.c:1.35->1.36 
#   F:pci/nm256/nm256.c:1.38->1.39 
#   L:- Fix the mmap via io_remap_page_range() on nm256, rme32 and rme96.
#   L:  Added SNDRV_PCM_INFO_MMAP_IOMEM to handle this case.
#   L:- Clean up the indirect accessing on RME32/RME96 drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/asound.h
#   2004/06/21 11:50:08+02:00 perex@suse.cz +1 -0
#   ALSA CVS update
#   D:2004/06/21 17:50:08
#   C:PCM Midlevel,ALSA Core,RME32 driver,RME96 driver,NM256 driver
#   F:core/pcm_native.c:1.92->1.93 
#   F:include/asound.h:1.40->1.41 
#   F:pci/rme32.c:1.33->1.34 
#   F:pci/rme96.c:1.35->1.36 
#   F:pci/nm256/nm256.c:1.38->1.39 
#   L:- Fix the mmap via io_remap_page_range() on nm256, rme32 and rme96.
#   L:  Added SNDRV_PCM_INFO_MMAP_IOMEM to handle this case.
#   L:- Clean up the indirect accessing on RME32/RME96 drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:11:34+02:00 perex@suse.cz 
#   ALSA CVS update
#   USB generic driver
#   handle devices that allow setting but not reading sample rate
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2004/06/21 09:45:12+02:00 perex@suse.cz +2 -2
#   ALSA CVS update
#   D:2004/06/21 15:45:12
#   C:USB generic driver
#   F:usb/usbaudio.c:1.101->1.102 
#   L:handle devices that allow setting but not reading sample rate
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 13:10:13+02:00 perex@suse.cz 
#   ALSA CVS update
#   VIA82xx driver
#   Fixed the calculation of the current DMA position at the period boundary.
#   
#   In some cases, DMA residue returns the value 0 during the transition
#   at the DMA boundary.  The patch handles it as the position 0.
#   This may prevent the flood of 'invalid last pointer' debug messages
#   on some devices.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/06/18 11:52:36+02:00 perex@suse.cz +5 -1
#   ALSA CVS update
#   D:2004/06/18 17:52:36
#   C:VIA82xx driver
#   F:pci/via82xx.c:1.104->1.105 
#   L:Fixed the calculation of the current DMA position at the period boundary.
#   L:
#   L:In some cases, DMA residue returns the value 0 during the transition
#   L:at the DMA boundary.  The patch handles it as the position 0.
#   L:This may prevent the flood of 'invalid last pointer' debug messages
#   L:on some devices.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:08:53+02:00 perex@suse.cz 
#   ALSA CVS update
#   Intel8x0 driver
#   Fixed the calculation of the current DMA position on some sloppy devices.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/06/18 11:50:52+02:00 perex@suse.cz +15 -9
#   ALSA CVS update
#   D:2004/06/18 17:50:52
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.138->1.139 
#   L:Fixed the calculation of the current DMA position on some sloppy devices.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:07:19+02:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   Trident driver
#   Clean up the buffer management in the PCM runtime record.
#   
#   The buffer-allocation record is hold in runtime instance, so that
#   it can be checked more cleanly.
#   
#   dma_private is removed from runtime (it's used for SG-buffers).
#   The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   access to the pointer, to retrieve the sgbuf struct from the PCM
#   substream instance.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/trident/trident_memory.c
#   2004/06/18 11:46:32+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/06/18 17:46:31
#   C:PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   C:Trident driver
#   F:core/pcm_memory.c:1.28->1.29 
#   F:include/pcm.h:1.41->1.42 
#   F:pci/es1968.c:1.67->1.68 
#   F:pci/emu10k1/memory.c:1.17->1.18 
#   F:pci/korg1212/korg1212.c:1.38->1.39 
#   F:pci/trident/trident_memory.c:1.14->1.15 
#   L:Clean up the buffer management in the PCM runtime record.
#   L:
#   L:The buffer-allocation record is hold in runtime instance, so that
#   L:it can be checked more cleanly.
#   L:
#   L:dma_private is removed from runtime (it's used for SG-buffers).
#   L:The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   L:access to the pointer, to retrieve the sgbuf struct from the PCM
#   L:substream instance.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/korg1212/korg1212.c
#   2004/06/18 11:46:32+02:00 perex@suse.cz +6 -4
#   ALSA CVS update
#   D:2004/06/18 17:46:31
#   C:PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   C:Trident driver
#   F:core/pcm_memory.c:1.28->1.29 
#   F:include/pcm.h:1.41->1.42 
#   F:pci/es1968.c:1.67->1.68 
#   F:pci/emu10k1/memory.c:1.17->1.18 
#   F:pci/korg1212/korg1212.c:1.38->1.39 
#   F:pci/trident/trident_memory.c:1.14->1.15 
#   L:Clean up the buffer management in the PCM runtime record.
#   L:
#   L:The buffer-allocation record is hold in runtime instance, so that
#   L:it can be checked more cleanly.
#   L:
#   L:dma_private is removed from runtime (it's used for SG-buffers).
#   L:The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   L:access to the pointer, to retrieve the sgbuf struct from the PCM
#   L:substream instance.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/es1968.c
#   2004/06/18 11:46:31+02:00 perex@suse.cz +32 -30
#   ALSA CVS update
#   D:2004/06/18 17:46:31
#   C:PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   C:Trident driver
#   F:core/pcm_memory.c:1.28->1.29 
#   F:include/pcm.h:1.41->1.42 
#   F:pci/es1968.c:1.67->1.68 
#   F:pci/emu10k1/memory.c:1.17->1.18 
#   F:pci/korg1212/korg1212.c:1.38->1.39 
#   F:pci/trident/trident_memory.c:1.14->1.15 
#   L:Clean up the buffer management in the PCM runtime record.
#   L:
#   L:The buffer-allocation record is hold in runtime instance, so that
#   L:it can be checked more cleanly.
#   L:
#   L:dma_private is removed from runtime (it's used for SG-buffers).
#   L:The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   L:access to the pointer, to retrieve the sgbuf struct from the PCM
#   L:substream instance.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/memory.c
#   2004/06/18 11:46:31+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/06/18 17:46:31
#   C:PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   C:Trident driver
#   F:core/pcm_memory.c:1.28->1.29 
#   F:include/pcm.h:1.41->1.42 
#   F:pci/es1968.c:1.67->1.68 
#   F:pci/emu10k1/memory.c:1.17->1.18 
#   F:pci/korg1212/korg1212.c:1.38->1.39 
#   F:pci/trident/trident_memory.c:1.14->1.15 
#   L:Clean up the buffer management in the PCM runtime record.
#   L:
#   L:The buffer-allocation record is hold in runtime instance, so that
#   L:it can be checked more cleanly.
#   L:
#   L:dma_private is removed from runtime (it's used for SG-buffers).
#   L:The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   L:access to the pointer, to retrieve the sgbuf struct from the PCM
#   L:substream instance.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_memory.c
#   2004/06/18 11:46:31+02:00 perex@suse.cz +18 -22
#   ALSA CVS update
#   D:2004/06/18 17:46:31
#   C:PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   C:Trident driver
#   F:core/pcm_memory.c:1.28->1.29 
#   F:include/pcm.h:1.41->1.42 
#   F:pci/es1968.c:1.67->1.68 
#   F:pci/emu10k1/memory.c:1.17->1.18 
#   F:pci/korg1212/korg1212.c:1.38->1.39 
#   F:pci/trident/trident_memory.c:1.14->1.15 
#   L:Clean up the buffer management in the PCM runtime record.
#   L:
#   L:The buffer-allocation record is hold in runtime instance, so that
#   L:it can be checked more cleanly.
#   L:
#   L:dma_private is removed from runtime (it's used for SG-buffers).
#   L:The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   L:access to the pointer, to retrieve the sgbuf struct from the PCM
#   L:substream instance.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/pcm.h
#   2004/06/18 11:46:31+02:00 perex@suse.cz +19 -2
#   ALSA CVS update
#   D:2004/06/18 17:46:31
#   C:PCM Midlevel,ES1968 driver,EMU10K1/EMU10K2 driver,KORG1212 driver
#   C:Trident driver
#   F:core/pcm_memory.c:1.28->1.29 
#   F:include/pcm.h:1.41->1.42 
#   F:pci/es1968.c:1.67->1.68 
#   F:pci/emu10k1/memory.c:1.17->1.18 
#   F:pci/korg1212/korg1212.c:1.38->1.39 
#   F:pci/trident/trident_memory.c:1.14->1.15 
#   L:Clean up the buffer management in the PCM runtime record.
#   L:
#   L:The buffer-allocation record is hold in runtime instance, so that
#   L:it can be checked more cleanly.
#   L:
#   L:dma_private is removed from runtime (it's used for SG-buffers).
#   L:The macro snd_pcm_substream_sgbuf() should be used instead of direct
#   L:access to the pointer, to retrieve the sgbuf struct from the PCM
#   L:substream instance.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:05:35+02:00 perex@suse.cz 
#   ALSA CVS update
#   Generic drivers
#   Do the buffer allocation in hw_params callback instead of open callback.
#   
#   This will prevent to use the allocation of excessive size.
#   Pre-allocation is called with the default size 0, ie. no buffer will be
#   pre-allocated as default.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/dummy.c
#   2004/06/18 11:43:33+02:00 perex@suse.cz +20 -31
#   ALSA CVS update
#   D:2004/06/18 17:43:33
#   C:Generic drivers
#   F:drivers/dummy.c:1.27->1.28 
#   L:Do the buffer allocation in hw_params callback instead of open callback.
#   L:
#   L:This will prevent to use the allocation of excessive size.
#   L:Pre-allocation is called with the default size 0, ie. no buffer will be
#   L:pre-allocated as default.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:04:14+02:00 perex@suse.cz 
#   ALSA CVS update
#   ES1968 driver
#   Fix the crash at unloading the module due to the shared interrupt
#   with other devices.
#   
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/es1968.c
#   2004/06/18 08:40:17+02:00 perex@suse.cz +2 -2
#   ALSA CVS update
#   D:2004/06/18 14:40:17
#   C:ES1968 driver
#   F:pci/es1968.c:1.66->1.67 
#   L:Fix the crash at unloading the module due to the shared interrupt
#   L:with other devices.
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:02:56+02:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel
#   Removed the obsoleted init for boot parameters.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_memory.c
#   2004/06/18 08:38:26+02:00 perex@suse.cz +0 -15
#   ALSA CVS update
#   D:2004/06/18 14:38:26
#   C:PCM Midlevel
#   F:core/pcm_memory.c:1.27->1.28 
#   L:Removed the obsoleted init for boot parameters.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 13:01:38+02:00 perex@suse.cz 
#   ALSA CVS update
#   CS46xx driver,MIXART driver
#   reduce stack usage
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/mixart/mixart.c
#   2004/06/16 08:32:20+02:00 perex@suse.cz +27 -19
#   ALSA CVS update
#   D:2004/06/16 14:35:18
#   C:CS46xx driver,MIXART driver
#   F:pci/cs46xx/dsp_spos.c:1.23->1.24 
#   F:pci/mixart/mixart.c:1.8->1.9 
#   L:reduce stack usage
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/cs46xx/dsp_spos.c
#   2004/06/16 08:35:18+02:00 perex@suse.cz +16 -11
#   ALSA CVS update
#   D:2004/06/16 14:35:18
#   C:CS46xx driver,MIXART driver
#   F:pci/cs46xx/dsp_spos.c:1.23->1.24 
#   F:pci/mixart/mixart.c:1.8->1.9 
#   L:reduce stack usage
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 12:58:32+02:00 perex@suse.cz 
#   ALSA CVS update
#   OSS sequencer emulation
#   
#   Use separate functions for some ioctls to reduce stack usage.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/seq/oss/seq_oss_ioctl.c
#   2004/06/23 12:58:02+02:00 perex@suse.cz +46 -28
#   ALSA CVS update
#   D:2004/06/16 14:28:13
#   C:ALSA<-OSS sequencer
#   F:core/seq/oss/seq_oss_ioctl.c:1.5->1.6 
#   L:use separate functions for some ioctls to reduce stack usage
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 12:44:07+02:00 perex@suse.cz 
#   ALSA CVS update
#   OPL4
#   add newline at end of file
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/opl4/Makefile
#   2004/06/16 04:46:02+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/06/16 10:46:02
#   C:OPL4
#   F:drivers/opl4/Makefile:1.3->1.4 
#   L:add newline at end of file
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 12:42:44+02:00 perex@suse.cz 
#   ALSA CVS update
#   Opti9xx drivers
#   Fixed spin deadlocks.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/opti9xx/opti92x-ad1848.c
#   2004/06/15 05:39:57+02:00 perex@suse.cz +2 -19
#   ALSA CVS update
#   D:2004/06/15 11:39:57
#   C:Opti9xx drivers
#   F:isa/opti9xx/opti92x-ad1848.c:1.44->1.45 
#   L:Fixed spin deadlocks.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 12:41:27+02:00 perex@suse.cz 
#   ALSA CVS update
#   USB generic driver
#   Quattro USB: handle the different endianness of playback and recording sample data
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2004/06/14 12:12:05+02:00 perex@suse.cz +36 -5
#   ALSA CVS update
#   D:2004/06/14 18:12:05
#   C:USB generic driver
#   F:usb/usbaudio.c:1.100->1.101 
#   F:usb/usbquirks.h:1.33->1.34 
#   L:Quattro USB: handle the different endianness of playback and recording sample data
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2004/06/14 12:12:05+02:00 perex@suse.cz +20 -6
#   ALSA CVS update
#   D:2004/06/14 18:12:05
#   C:USB generic driver
#   F:usb/usbaudio.c:1.100->1.101 
#   F:usb/usbquirks.h:1.33->1.34 
#   L:Quattro USB: handle the different endianness of playback and recording sample data
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/06/23 12:40:10+02:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel,ALSA<-OSS emulation
#   Clean up and optimization of PCM format-specific functions.
#   
#   - Use array indexing instead of huge swith/case.
#   - Removed superfluous handling of floats.
#   - Use memcpy for silencing to simplify the codes.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_misc.c
#   2004/06/09 12:36:14+02:00 perex@suse.cz +249 -459
#   ALSA CVS update
#   D:2004/06/09 18:36:14
#   C:PCM Midlevel,ALSA<-OSS emulation
#   F:core/pcm_misc.c:1.13->1.14 
#   F:core/oss/pcm_plugin.c:1.18->1.19 
#   F:include/pcm.h:1.40->1.41 
#   L:Clean up and optimization of PCM format-specific functions.
#   L:
#   L:- Use array indexing instead of huge swith/case.
#   L:- Removed superfluous handling of floats.
#   L:- Use memcpy for silencing to simplify the codes.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/oss/pcm_plugin.c
#   2004/06/09 12:36:14+02:00 perex@suse.cz +27 -96
#   ALSA CVS update
#   D:2004/06/09 18:36:14
#   C:PCM Midlevel,ALSA<-OSS emulation
#   F:core/pcm_misc.c:1.13->1.14 
#   F:core/oss/pcm_plugin.c:1.18->1.19 
#   F:include/pcm.h:1.40->1.41 
#   L:Clean up and optimization of PCM format-specific functions.
#   L:
#   L:- Use array indexing instead of huge swith/case.
#   L:- Removed superfluous handling of floats.
#   L:- Use memcpy for silencing to simplify the codes.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/pcm.h
#   2004/06/09 12:36:15+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/06/09 18:36:14
#   C:PCM Midlevel,ALSA<-OSS emulation
#   F:core/pcm_misc.c:1.13->1.14 
#   F:core/oss/pcm_plugin.c:1.18->1.19 
#   F:include/pcm.h:1.40->1.41 
#   L:Clean up and optimization of PCM format-specific functions.
#   L:
#   L:- Use array indexing instead of huge swith/case.
#   L:- Removed superfluous handling of floats.
#   L:- Use memcpy for silencing to simplify the codes.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 12:38:51+02:00 perex@suse.cz 
#   ALSA CVS update
#   Intel8x0 driver
#   Added the PCI ID for nVidia CK8.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/06/09 12:02:00+02:00 perex@suse.cz +5 -0
#   ALSA CVS update
#   D:2004/06/09 18:02:00
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.137->1.138 
#   L:Added the PCI ID for nVidia CK8.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 12:37:24+02:00 perex@suse.cz 
#   ALSA CVS update
#   ATIIXP driver,VIA82xx driver
#   Added the missing RESUME info bits to pcm.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/06/09 12:01:05+02:00 perex@suse.cz +1 -0
#   ALSA CVS update
#   D:2004/06/09 18:01:05
#   C:ATIIXP driver,VIA82xx driver
#   F:pci/atiixp.c:1.10->1.11 
#   F:pci/via82xx.c:1.103->1.104 
#   L:Added the missing RESUME info bits to pcm.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp.c
#   2004/06/09 12:01:05+02:00 perex@suse.cz +1 -0
#   ALSA CVS update
#   D:2004/06/09 18:01:05
#   C:ATIIXP driver,VIA82xx driver
#   F:pci/atiixp.c:1.10->1.11 
#   F:pci/via82xx.c:1.103->1.104 
#   L:Added the missing RESUME info bits to pcm.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 12:33:49+02:00 perex@suse.cz 
#   ALSA CVS update
#   ICE1724 driver
#   SPDIF output fixes
#   
#   - Fixed the encoding of SPDIF status bits in the consumer mode.
#   - Change the SPDIF status bits according to the current sample rate.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1724.c
#   2004/06/08 11:15:26+02:00 perex@suse.cz +40 -11
#   ALSA CVS update
#   D:2004/06/08 17:15:26
#   C:ICE1724 driver
#   F:pci/ice1712/ice1724.c:1.33->1.34 
#   L:SPDIF output fixes
#   L:
#   L:- Fixed the encoding of SPDIF status bits in the consumer mode.
#   L:- Change the SPDIF status bits according to the current sample rate.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/06/23 12:28:34+02:00 perex@suse.cz 
#   ALSA CVS update
#   Documentation
#   Added snd-fm801 tuner parameter description
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2004/06/01 02:56:20+02:00 perex@suse.cz +7 -0
#   ALSA CVS update
#   D:2004/06/01 08:56:20
#   C:Documentation
#   F:Documentation/ALSA-Configuration.txt:1.45->1.46 
#   L:Added snd-fm801 tuner parameter description
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/06/18 11:41:03-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/06/18 11:40:59-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/16 11:59:16+02:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5
#   into suse.cz:/home/perex/bk/linux-sound/linux-sound
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/06/16 11:58:53+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/core/seq/seq_clientmgr.c
#   2004/06/16 11:58:53+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/vx_core.h
#   2004/06/16 11:58:53+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/seq_kernel.h
#   2004/06/16 11:58:53+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/core.h
#   2004/06/16 11:58:53+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/15 21:01:33-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/06/15 21:01:29-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/04 02:14:21-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/sound/vx_core.h
#   2004/06/04 02:14:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/03 18:39:45-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/06/03 18:39:42-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# sound/core/seq/seq_clientmgr.c
#   2004/06/03 18:39:42-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/sound/seq_kernel.h
#   2004/06/03 18:39:42-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/sound/core.h
#   2004/06/03 18:39:42-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/03 10:17:49-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/06/03 10:17:46-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/02 13:14:41-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/06/02 13:14:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/31 16:02:35-07:00 akpm@bix.(none) 
#   Merge http://linux-sound.bkbits.net/linux-sound
#   into bix.(none):/usr/src/bk-alsa
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/05/31 16:02:31-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/31 08:49:28+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   AC97 Codec Core
#   Fixed mutex deadlocks.
# 
# sound/pci/ac97/ac97_patch.c
#   2004/05/30 11:40:05+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/05/30 17:40:04
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.135->1.136 
#   F:pci/ac97/ac97_patch.c:1.52->1.53 
#   L:Fixed mutex deadlocks.
# 
# sound/pci/ac97/ac97_codec.c
#   2004/05/30 11:40:04+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/05/30 17:40:04
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.135->1.136 
#   F:pci/ac97/ac97_patch.c:1.52->1.53 
#   L:Fixed mutex deadlocks.
# 
# ChangeSet
#   2004/05/30 14:01:08+02:00 perex@suse.cz 
#   ALSA 1.0.5
# 
# include/sound/version.h
#   2004/05/30 14:00:09+02:00 perex@suse.cz +2 -2
#   ALSA 1.0.5
# 
# ChangeSet
#   2004/05/30 13:57:33+02:00 perex@suse.cz 
#   ALSA CVS update - Jaroslav Kysela <perex@suse.cz>
#   ALSA Core
#   Fixed warnings for pci PM callbacks when not CONFIG_PCI
# 
# include/sound/core.h
#   2004/05/30 06:50:15+02:00 perex@suse.cz +4 -0
#   ALSA CVS update
#   D:2004/05/30 12:50:15
#   C:ALSA Core
#   A:Jaroslav Kysela <perex@suse.cz>
#   F:include/core.h:1.51->1.52 
#   L:Fixed warnings for pci PM callbacks when not CONFIG_PCI
# 
# ChangeSet
#   2004/05/28 16:58:34-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/28 16:58:31-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/28 13:15:53-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/28 13:15:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/28 15:04:32+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   AC97 Codec Core
#   - Added the single mixer control with AC97 2.3 paging.
#   - Handle the paging for some ALC655/658 registers.
#   - Added the experimental support for ALC850.
# 
# sound/pci/ac97/ac97_patch.h
#   2004/05/28 04:27:09+02:00 perex@suse.cz +1 -0
#   ALSA CVS update
#   D:2004/05/28 10:27:09
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.134->1.135 
#   F:pci/ac97/ac97_id.h:1.8->1.9 
#   F:pci/ac97/ac97_local.h:1.6->1.7 
#   F:pci/ac97/ac97_patch.c:1.51->1.52 
#   F:pci/ac97/ac97_patch.h:1.15->1.16 
#   L:- Added the single mixer control with AC97 2.3 paging.
#   L:- Handle the paging for some ALC655/658 registers.
#   L:- Added the experimental support for ALC850.
# 
# sound/pci/ac97/ac97_patch.c
#   2004/05/28 04:27:09+02:00 perex@suse.cz +148 -28
#   ALSA CVS update
#   D:2004/05/28 10:27:09
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.134->1.135 
#   F:pci/ac97/ac97_id.h:1.8->1.9 
#   F:pci/ac97/ac97_local.h:1.6->1.7 
#   F:pci/ac97/ac97_patch.c:1.51->1.52 
#   F:pci/ac97/ac97_patch.h:1.15->1.16 
#   L:- Added the single mixer control with AC97 2.3 paging.
#   L:- Handle the paging for some ALC655/658 registers.
#   L:- Added the experimental support for ALC850.
# 
# sound/pci/ac97/ac97_local.h
#   2004/05/28 04:27:09+02:00 perex@suse.cz +7 -0
#   ALSA CVS update
#   D:2004/05/28 10:27:09
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.134->1.135 
#   F:pci/ac97/ac97_id.h:1.8->1.9 
#   F:pci/ac97/ac97_local.h:1.6->1.7 
#   F:pci/ac97/ac97_patch.c:1.51->1.52 
#   F:pci/ac97/ac97_patch.h:1.15->1.16 
#   L:- Added the single mixer control with AC97 2.3 paging.
#   L:- Handle the paging for some ALC655/658 registers.
#   L:- Added the experimental support for ALC850.
# 
# sound/pci/ac97/ac97_id.h
#   2004/05/28 04:27:09+02:00 perex@suse.cz +7 -0
#   ALSA CVS update
#   D:2004/05/28 10:27:09
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.134->1.135 
#   F:pci/ac97/ac97_id.h:1.8->1.9 
#   F:pci/ac97/ac97_local.h:1.6->1.7 
#   F:pci/ac97/ac97_patch.c:1.51->1.52 
#   F:pci/ac97/ac97_patch.h:1.15->1.16 
#   L:- Added the single mixer control with AC97 2.3 paging.
#   L:- Handle the paging for some ALC655/658 registers.
#   L:- Added the experimental support for ALC850.
# 
# sound/pci/ac97/ac97_codec.c
#   2004/05/28 04:27:09+02:00 perex@suse.cz +61 -18
#   ALSA CVS update
#   D:2004/05/28 10:27:09
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.134->1.135 
#   F:pci/ac97/ac97_id.h:1.8->1.9 
#   F:pci/ac97/ac97_local.h:1.6->1.7 
#   F:pci/ac97/ac97_patch.c:1.51->1.52 
#   F:pci/ac97/ac97_patch.h:1.15->1.16 
#   L:- Added the single mixer control with AC97 2.3 paging.
#   L:- Handle the paging for some ALC655/658 registers.
#   L:- Added the experimental support for ALC850.
# 
# ChangeSet
#   2004/05/28 15:04:07+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   AC97 Codec Core
#   Avoid warning message during codec probing in case SKIP_AUDIO flag is not set.
# 
# sound/pci/ac97/ac97_codec.c
#   2004/05/27 13:15:54+02:00 perex@suse.cz +6 -4
#   ALSA CVS update
#   D:2004/05/27 19:15:54
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ac97/ac97_codec.c:1.133->1.134 
#   L:Avoid warning message during codec probing in case SKIP_AUDIO flag is not set.
# 
# ChangeSet
#   2004/05/28 15:03:42+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   PARISC Harmony driver
#   fixed typos.
# 
# sound/parisc/harmony.c
#   2004/05/26 11:02:12+02:00 perex@suse.cz +2 -2
#   ALSA CVS update
#   D:2004/05/26 17:02:12
#   C:PARISC Harmony driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:parisc/harmony.c:1.11->1.12 
#   L:fixed typos.
# 
# ChangeSet
#   2004/05/28 15:03:20+02:00 perex@suse.cz 
#   ALSA CVS update - Jaroslav Kysela <perex@suse.cz>
#   AC97 Codec Core
#   Signed-off-by: Kevin Mack <kevmack@accesscomm.ca>
#   For Gateway M675 notebook - this will direct mixer
#   output to speaker, headphone and line-out instead
#   of just the front(DAC-A) signal.
# 
# sound/pci/ac97/ac97_patch.c
#   2004/05/26 02:34:55+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/05/26 08:34:55
#   C:AC97 Codec Core
#   A:Jaroslav Kysela <perex@suse.cz>
#   F:pci/ac97/ac97_patch.c:1.50->1.51 
#   L:Signed-off-by: Kevin Mack <kevmack@accesscomm.ca>
#   L:For Gateway M675 notebook - this will direct mixer
#   L:output to speaker, headphone and line-out instead
#   L:of just the front(DAC-A) signal.
# 
# ChangeSet
#   2004/05/28 15:02:56+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   VIA82xx driver
#   - use snd_pcm_limit_hw_rates() and removed redundant codes.
#   - fixed the rate constraints when 'IEC958 Output Switch' is on.
#   - check the SPDIF support on AC97 and don't build IEC958 stuffs if not available.
# 
# sound/pci/via82xx.c
#   2004/05/25 12:54:55+02:00 perex@suse.cz +15 -38
#   ALSA CVS update
#   D:2004/05/25 18:54:55
#   C:VIA82xx driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/via82xx.c:1.102->1.103 
#   L:- use snd_pcm_limit_hw_rates() and removed redundant codes.
#   L:- fixed the rate constraints when 'IEC958 Output Switch' is on.
#   L:- check the SPDIF support on AC97 and don't build IEC958 stuffs if not available.
# 
# ChangeSet
#   2004/05/28 15:02:35+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   AC97 Codec Core
#   added ac97_can_spdif() for checking the SPDIF support.
# 
# include/sound/ac97_codec.h
#   2004/05/25 12:52:57+02:00 perex@suse.cz +4 -0
#   ALSA CVS update
#   D:2004/05/25 18:52:57
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:include/ac97_codec.h:1.45->1.46 
#   L:added ac97_can_spdif() for checking the SPDIF support.
# 
# ChangeSet
#   2004/05/28 15:02:13+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   VIA82xx driver
#   added the DXS entry for Mitac/Vobis/Yakumo laptop.
# 
# sound/pci/via82xx.c
#   2004/05/25 10:10:38+02:00 perex@suse.cz +1 -0
#   ALSA CVS update
#   D:2004/05/25 16:10:38
#   C:VIA82xx driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/via82xx.c:1.101->1.102 
#   L:added the DXS entry for Mitac/Vobis/Yakumo laptop.
# 
# ChangeSet
#   2004/05/28 15:01:53+02:00 perex@suse.cz 
#   ALSA CVS update - Clemens Ladisch <clemens@ladisch.de>
#   Wavefront drivers
#   fix possible buffer overflow in wavefront_download_firmware()
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/05/25 07:10:48+02:00 perex@suse.cz +6 -0
#   ALSA CVS update
#   D:2004/05/25 13:10:48
#   C:Wavefront drivers
#   A:Clemens Ladisch <clemens@ladisch.de>
#   F:isa/wavefront/wavefront_synth.c:1.17->1.18 
#   L:fix possible buffer overflow in wavefront_download_firmware()
# 
# ChangeSet
#   2004/05/28 14:20:37+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   ICE1724 driver
#   avoid to change the AC97 rate registers.  this seems conflicting
#   with the rate conversion on VT172x.
# 
# sound/pci/ice1712/ice1724.c
#   2004/05/25 04:56:22+02:00 perex@suse.cz +2 -17
#   ALSA CVS update
#   D:2004/05/25 10:56:22
#   C:ICE1724 driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/ice1712/ice1724.c:1.32->1.33 
#   L:avoid to change the AC97 rate registers.  this seems conflicting
#   L:with the rate conversion on VT172x.
# 
# ChangeSet
#   2004/05/28 14:20:17+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   Digigram VX core
#   added 'Clock Mode' control to choose the clock source.
# 
# sound/drivers/vx/vx_uer.c
#   2004/05/24 12:12:43+02:00 perex@suse.cz +8 -7
#   ALSA CVS update
#   D:2004/05/24 18:12:43
#   C:Digigram VX core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:drivers/vx/vx_core.c:1.7->1.8 
#   F:drivers/vx/vx_mixer.c:1.2->1.3 
#   F:drivers/vx/vx_uer.c:1.1->1.2 
#   F:include/vx_core.h:1.1->1.2 
#   L:added 'Clock Mode' control to choose the clock source.
# 
# sound/drivers/vx/vx_mixer.c
#   2004/05/24 12:12:43+02:00 perex@suse.cz +51 -0
#   ALSA CVS update
#   D:2004/05/24 18:12:43
#   C:Digigram VX core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:drivers/vx/vx_core.c:1.7->1.8 
#   F:drivers/vx/vx_mixer.c:1.2->1.3 
#   F:drivers/vx/vx_uer.c:1.1->1.2 
#   F:include/vx_core.h:1.1->1.2 
#   L:added 'Clock Mode' control to choose the clock source.
# 
# sound/drivers/vx/vx_core.c
#   2004/05/24 12:12:43+02:00 perex@suse.cz +3 -0
#   ALSA CVS update
#   D:2004/05/24 18:12:43
#   C:Digigram VX core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:drivers/vx/vx_core.c:1.7->1.8 
#   F:drivers/vx/vx_mixer.c:1.2->1.3 
#   F:drivers/vx/vx_uer.c:1.1->1.2 
#   F:include/vx_core.h:1.1->1.2 
#   L:added 'Clock Mode' control to choose the clock source.
# 
# include/sound/vx_core.h
#   2004/05/24 12:12:43+02:00 perex@suse.cz +8 -0
#   ALSA CVS update
#   D:2004/05/24 18:12:43
#   C:Digigram VX core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:drivers/vx/vx_core.c:1.7->1.8 
#   F:drivers/vx/vx_mixer.c:1.2->1.3 
#   F:drivers/vx/vx_uer.c:1.1->1.2 
#   F:include/vx_core.h:1.1->1.2 
#   L:added 'Clock Mode' control to choose the clock source.
# 
# ChangeSet
#   2004/05/28 14:19:53+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   Digigram VX core
#   fixed the compile warnings due to the last change.
# 
# sound/drivers/vx/vx_pcm.c
#   2004/05/24 12:11:58+02:00 perex@suse.cz +2 -1
#   ALSA CVS update
#   D:2004/05/24 18:11:58
#   C:Digigram VX core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:drivers/vx/vx_pcm.c:1.4->1.5 
#   L:fixed the compile warnings due to the last change.
# 
# ChangeSet
#   2004/05/28 14:19:28+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   PARISC Harmony driver
#   - fixed the buffer handling without dma_alloc_coherent support.
# 
# sound/parisc/harmony.c
#   2004/05/24 09:51:51+02:00 perex@suse.cz +31 -9
#   ALSA CVS update
#   D:2004/05/24 15:51:51
#   C:PARISC Harmony driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:parisc/harmony.c:1.10->1.11 
#   L:- fixed the buffer handling without dma_alloc_coherent support.
# 
# ChangeSet
#   2004/05/28 14:19:07+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   Digigram VX core
#   fixed sleep while atomic in the trigger callback.
# 
# sound/drivers/vx/vx_pcm.c
#   2004/05/24 09:06:17+02:00 perex@suse.cz +2 -8
#   ALSA CVS update
#   D:2004/05/24 15:06:17
#   C:Digigram VX core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:drivers/vx/vx_pcm.c:1.3->1.4 
#   L:fixed sleep while atomic in the trigger callback.
# 
# ChangeSet
#   2004/05/28 14:14:19+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   AC97 Codec Core
#   - added the global mutex for ac97_t (ad18xx mutex is removed).
#     used to protect paging and AD18xx multi-codecs.
#   - set PAGE_INT register explicitly before accessing (for STAC9758).
#   - moved ALC650 revision check to patch_alc650().
#   - support stereo Mic playback.
#   - moved STAC9708 quirk to patch_stac9708().
#   - don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
#   - avoid the unnecessary RESET-waiting for audio/modem codec.
#   - fixed the evaluation of modem codec to call mpatch callback properly.
#   - determine the SPDIF rate in the build path.
#   - added suffix argument to snd_ac97_rename|remove|swap_ctl().
#   - added snd_ac97_rename_vol_ctl().
# 
# sound/pci/ac97/ac97_proc.c
#   2004/05/24 08:24:42+02:00 perex@suse.cz +6 -4
#   ALSA CVS update
#   D:2004/05/24 14:24:42
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:include/ac97_codec.h:1.44->1.45 
#   F:pci/ac97/ac97_codec.c:1.132->1.133 
#   F:pci/ac97/ac97_local.h:1.5->1.6 
#   F:pci/ac97/ac97_patch.c:1.49->1.50 
#   F:pci/ac97/ac97_proc.c:1.7->1.8 
#   L:- added the global mutex for ac97_t (ad18xx mutex is removed).
#   L:  used to protect paging and AD18xx multi-codecs.
#   L:- set PAGE_INT register explicitly before accessing (for STAC9758).
#   L:- moved ALC650 revision check to patch_alc650().
#   L:- support stereo Mic playback.
#   L:- moved STAC9708 quirk to patch_stac9708().
#   L:- don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
#   L:- avoid the unnecessary RESET-waiting for audio/modem codec.
#   L:- fixed the evaluation of modem codec to call mpatch callback properly.
#   L:- determine the SPDIF rate in the build path.
#   L:- added suffix argument to snd_ac97_rename|remove|swap_ctl().
#   L:- added snd_ac97_rename_vol_ctl().
# 
# sound/pci/ac97/ac97_patch.c
#   2004/05/24 08:24:42+02:00 perex@suse.cz +75 -30
#   ALSA CVS update
#   D:2004/05/24 14:24:42
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:include/ac97_codec.h:1.44->1.45 
#   F:pci/ac97/ac97_codec.c:1.132->1.133 
#   F:pci/ac97/ac97_local.h:1.5->1.6 
#   F:pci/ac97/ac97_patch.c:1.49->1.50 
#   F:pci/ac97/ac97_proc.c:1.7->1.8 
#   L:- added the global mutex for ac97_t (ad18xx mutex is removed).
#   L:  used to protect paging and AD18xx multi-codecs.
#   L:- set PAGE_INT register explicitly before accessing (for STAC9758).
#   L:- moved ALC650 revision check to patch_alc650().
#   L:- support stereo Mic playback.
#   L:- moved STAC9708 quirk to patch_stac9708().
#   L:- don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
#   L:- avoid the unnecessary RESET-waiting for audio/modem codec.
#   L:- fixed the evaluation of modem codec to call mpatch callback properly.
#   L:- determine the SPDIF rate in the build path.
#   L:- added suffix argument to snd_ac97_rename|remove|swap_ctl().
#   L:- added snd_ac97_rename_vol_ctl().
# 
# sound/pci/ac97/ac97_local.h
#   2004/05/24 08:24:42+02:00 perex@suse.cz +4 -3
#   ALSA CVS update
#   D:2004/05/24 14:24:42
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:include/ac97_codec.h:1.44->1.45 
#   F:pci/ac97/ac97_codec.c:1.132->1.133 
#   F:pci/ac97/ac97_local.h:1.5->1.6 
#   F:pci/ac97/ac97_patch.c:1.49->1.50 
#   F:pci/ac97/ac97_proc.c:1.7->1.8 
#   L:- added the global mutex for ac97_t (ad18xx mutex is removed).
#   L:  used to protect paging and AD18xx multi-codecs.
#   L:- set PAGE_INT register explicitly before accessing (for STAC9758).
#   L:- moved ALC650 revision check to patch_alc650().
#   L:- support stereo Mic playback.
#   L:- moved STAC9708 quirk to patch_stac9708().
#   L:- don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
#   L:- avoid the unnecessary RESET-waiting for audio/modem codec.
#   L:- fixed the evaluation of modem codec to call mpatch callback properly.
#   L:- determine the SPDIF rate in the build path.
#   L:- added suffix argument to snd_ac97_rename|remove|swap_ctl().
#   L:- added snd_ac97_rename_vol_ctl().
# 
# sound/pci/ac97/ac97_codec.c
#   2004/05/24 08:24:42+02:00 perex@suse.cz +93 -70
#   ALSA CVS update
#   D:2004/05/24 14:24:42
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:include/ac97_codec.h:1.44->1.45 
#   F:pci/ac97/ac97_codec.c:1.132->1.133 
#   F:pci/ac97/ac97_local.h:1.5->1.6 
#   F:pci/ac97/ac97_patch.c:1.49->1.50 
#   F:pci/ac97/ac97_proc.c:1.7->1.8 
#   L:- added the global mutex for ac97_t (ad18xx mutex is removed).
#   L:  used to protect paging and AD18xx multi-codecs.
#   L:- set PAGE_INT register explicitly before accessing (for STAC9758).
#   L:- moved ALC650 revision check to patch_alc650().
#   L:- support stereo Mic playback.
#   L:- moved STAC9708 quirk to patch_stac9708().
#   L:- don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
#   L:- avoid the unnecessary RESET-waiting for audio/modem codec.
#   L:- fixed the evaluation of modem codec to call mpatch callback properly.
#   L:- determine the SPDIF rate in the build path.
#   L:- added suffix argument to snd_ac97_rename|remove|swap_ctl().
#   L:- added snd_ac97_rename_vol_ctl().
# 
# include/sound/ac97_codec.h
#   2004/05/24 08:24:42+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/05/24 14:24:42
#   C:AC97 Codec Core
#   A:Takashi Iwai <tiwai@suse.de>
#   F:include/ac97_codec.h:1.44->1.45 
#   F:pci/ac97/ac97_codec.c:1.132->1.133 
#   F:pci/ac97/ac97_local.h:1.5->1.6 
#   F:pci/ac97/ac97_patch.c:1.49->1.50 
#   F:pci/ac97/ac97_proc.c:1.7->1.8 
#   L:- added the global mutex for ac97_t (ad18xx mutex is removed).
#   L:  used to protect paging and AD18xx multi-codecs.
#   L:- set PAGE_INT register explicitly before accessing (for STAC9758).
#   L:- moved ALC650 revision check to patch_alc650().
#   L:- support stereo Mic playback.
#   L:- moved STAC9708 quirk to patch_stac9708().
#   L:- don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
#   L:- avoid the unnecessary RESET-waiting for audio/modem codec.
#   L:- fixed the evaluation of modem codec to call mpatch callback properly.
#   L:- determine the SPDIF rate in the build path.
#   L:- added suffix argument to snd_ac97_rename|remove|swap_ctl().
#   L:- added snd_ac97_rename_vol_ctl().
# 
# ChangeSet
#   2004/05/28 14:13:55+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   Memalloc module
#   - added ifdef CONFIG_PCI around the enable module option to avoid the compile
#     warnings without PCI support.
# 
# sound/core/memalloc.c
#   2004/05/24 08:19:55+02:00 perex@suse.cz +4 -0
#   ALSA CVS update
#   D:2004/05/24 14:19:55
#   C:Memalloc module
#   A:Takashi Iwai <tiwai@suse.de>
#   F:core/memalloc.c:1.31->1.32 
#   L:- added ifdef CONFIG_PCI around the enable module option to avoid the compile
#   L:  warnings without PCI support.
# 
# ChangeSet
#   2004/05/28 14:13:31+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   Documentation,ICE1712 driver,ICE1724 driver
#   - fixed the description of model module parameters for ice1712 and ice1724
#     drivers.
#   - added the support of VT1720-based mobo.
#     (still experimental and supporting AC97 only)
# 
# sound/pci/ice1712/vt1720_mobo.h
#   2004/05/28 13:46:26+02:00 perex@suse.cz +35 -0
#   ALSA CVS update
#   D:2004/05/24 14:18:20
#   C:Documentation,ICE1712 driver,ICE1724 driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:Documentation/ALSA-Configuration.txt:1.44->1.45 
#   F:pci/ice1712/Makefile:1.11->1.12 
#   F:pci/ice1712/ice1724.c:1.31->1.32 
#   F:pci/ice1712/vt1720_mobo.c:INITIAL->1.1 
#   F:pci/ice1712/vt1720_mobo.h:INITIAL->1.1 
#   L:- fixed the description of model module parameters for ice1712 and ice1724
#   L:  drivers.
#   L:- added the support of VT1720-based mobo.
#   L:  (still experimental and supporting AC97 only)
# 
# sound/pci/ice1712/vt1720_mobo.h
#   2004/05/28 13:46:26+02:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/vt1720_mobo.h
# 
# sound/pci/ice1712/vt1720_mobo.c
#   2004/05/28 13:46:21+02:00 perex@suse.cz +97 -0
#   ALSA CVS update
#   D:2004/05/24 14:18:20
#   C:Documentation,ICE1712 driver,ICE1724 driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:Documentation/ALSA-Configuration.txt:1.44->1.45 
#   F:pci/ice1712/Makefile:1.11->1.12 
#   F:pci/ice1712/ice1724.c:1.31->1.32 
#   F:pci/ice1712/vt1720_mobo.c:INITIAL->1.1 
#   F:pci/ice1712/vt1720_mobo.h:INITIAL->1.1 
#   L:- fixed the description of model module parameters for ice1712 and ice1724
#   L:  drivers.
#   L:- added the support of VT1720-based mobo.
#   L:  (still experimental and supporting AC97 only)
# 
# sound/pci/ice1712/ice1724.c
#   2004/05/24 08:18:20+02:00 perex@suse.cz +6 -6
#   ALSA CVS update
#   D:2004/05/24 14:18:20
#   C:Documentation,ICE1712 driver,ICE1724 driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:Documentation/ALSA-Configuration.txt:1.44->1.45 
#   F:pci/ice1712/Makefile:1.11->1.12 
#   F:pci/ice1712/ice1724.c:1.31->1.32 
#   F:pci/ice1712/vt1720_mobo.c:INITIAL->1.1 
#   F:pci/ice1712/vt1720_mobo.h:INITIAL->1.1 
#   L:- fixed the description of model module parameters for ice1712 and ice1724
#   L:  drivers.
#   L:- added the support of VT1720-based mobo.
#   L:  (still experimental and supporting AC97 only)
# 
# sound/pci/ice1712/Makefile
#   2004/05/24 08:18:20+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/05/24 14:18:20
#   C:Documentation,ICE1712 driver,ICE1724 driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:Documentation/ALSA-Configuration.txt:1.44->1.45 
#   F:pci/ice1712/Makefile:1.11->1.12 
#   F:pci/ice1712/ice1724.c:1.31->1.32 
#   F:pci/ice1712/vt1720_mobo.c:INITIAL->1.1 
#   F:pci/ice1712/vt1720_mobo.h:INITIAL->1.1 
#   L:- fixed the description of model module parameters for ice1712 and ice1724
#   L:  drivers.
#   L:- added the support of VT1720-based mobo.
#   L:  (still experimental and supporting AC97 only)
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2004/05/24 08:18:20+02:00 perex@suse.cz +3 -2
#   ALSA CVS update
#   D:2004/05/24 14:18:20
#   C:Documentation,ICE1712 driver,ICE1724 driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:Documentation/ALSA-Configuration.txt:1.44->1.45 
#   F:pci/ice1712/Makefile:1.11->1.12 
#   F:pci/ice1712/ice1724.c:1.31->1.32 
#   F:pci/ice1712/vt1720_mobo.c:INITIAL->1.1 
#   F:pci/ice1712/vt1720_mobo.h:INITIAL->1.1 
#   L:- fixed the description of model module parameters for ice1712 and ice1724
#   L:  drivers.
#   L:- added the support of VT1720-based mobo.
#   L:  (still experimental and supporting AC97 only)
# 
# sound/pci/ice1712/vt1720_mobo.c
#   2004/05/28 13:46:21+02:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/vt1720_mobo.c
# 
# ChangeSet
#   2004/05/28 14:13:07+02:00 perex@suse.cz 
#   ALSA CVS update - Takashi Iwai <tiwai@suse.de>
#   ATIIXP driver
#   - continue to probe other codecs even if a codec returns error
#     (instead of breaking the probing).
#     this will fix some cases with both AC97 and MC97 codecs.
# 
# sound/pci/atiixp.c
#   2004/05/24 08:16:43+02:00 perex@suse.cz +4 -12
#   ALSA CVS update
#   D:2004/05/24 14:16:43
#   C:ATIIXP driver
#   A:Takashi Iwai <tiwai@suse.de>
#   F:pci/atiixp.c:1.9->1.10 
#   L:- continue to probe other codecs even if a codec returns error
#   L:  (instead of breaking the probing).
#   L:  this will fix some cases with both AC97 and MC97 codecs.
# 
# ChangeSet
#   2004/05/28 14:12:17+02:00 perex@suse.cz 
#   ALSA CVS update - Clemens Ladisch <clemens@ladisch.de>
#   ALSA sequencer,ALSA<-OSS sequencer
#   export snd_seq_set_queue_tempo() for OSS to prevent calling
#   snd_seq_kernel_client_ctl() (using copy_from_user()) in interrupt
#   context
# 
# sound/core/seq/seq_clientmgr.c
#   2004/05/24 07:31:18+02:00 perex@suse.cz +9 -9
#   ALSA CVS update
#   D:2004/05/24 13:31:18
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   A:Clemens Ladisch <clemens@ladisch.de>
#   F:core/seq/seq.c:1.12->1.13 
#   F:core/seq/seq_clientmgr.c:1.28->1.29 
#   F:core/seq/oss/seq_oss_timer.c:1.5->1.6 
#   F:include/seq_kernel.h:1.9->1.10 
#   L:export snd_seq_set_queue_tempo() for OSS to prevent calling
#   L:snd_seq_kernel_client_ctl() (using copy_from_user()) in interrupt
#   L:context
# 
# sound/core/seq/seq.c
#   2004/05/24 07:31:18+02:00 perex@suse.cz +1 -0
#   ALSA CVS update
#   D:2004/05/24 13:31:18
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   A:Clemens Ladisch <clemens@ladisch.de>
#   F:core/seq/seq.c:1.12->1.13 
#   F:core/seq/seq_clientmgr.c:1.28->1.29 
#   F:core/seq/oss/seq_oss_timer.c:1.5->1.6 
#   F:include/seq_kernel.h:1.9->1.10 
#   L:export snd_seq_set_queue_tempo() for OSS to prevent calling
#   L:snd_seq_kernel_client_ctl() (using copy_from_user()) in interrupt
#   L:context
# 
# sound/core/seq/oss/seq_oss_timer.c
#   2004/05/24 07:31:19+02:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2004/05/24 13:31:18
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   A:Clemens Ladisch <clemens@ladisch.de>
#   F:core/seq/seq.c:1.12->1.13 
#   F:core/seq/seq_clientmgr.c:1.28->1.29 
#   F:core/seq/oss/seq_oss_timer.c:1.5->1.6 
#   F:include/seq_kernel.h:1.9->1.10 
#   L:export snd_seq_set_queue_tempo() for OSS to prevent calling
#   L:snd_seq_kernel_client_ctl() (using copy_from_user()) in interrupt
#   L:context
# 
# include/sound/seq_kernel.h
#   2004/05/24 07:31:18+02:00 perex@suse.cz +3 -0
#   ALSA CVS update
#   D:2004/05/24 13:31:18
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   A:Clemens Ladisch <clemens@ladisch.de>
#   F:core/seq/seq.c:1.12->1.13 
#   F:core/seq/seq_clientmgr.c:1.28->1.29 
#   F:core/seq/oss/seq_oss_timer.c:1.5->1.6 
#   F:include/seq_kernel.h:1.9->1.10 
#   L:export snd_seq_set_queue_tempo() for OSS to prevent calling
#   L:snd_seq_kernel_client_ctl() (using copy_from_user()) in interrupt
#   L:context
# 
# ChangeSet
#   2004/05/24 11:20:24-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# sound/pci/au88x0/au88x0_game.c
#   2004/05/24 11:20:20-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/pci_ids.h
#   2004/05/24 11:20:20-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/22 23:24:51-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/22 23:24:48-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/18 23:40:49-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# sound/pci/au88x0/au88x0_game.c
#   2004/05/18 23:40:46-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/pci_ids.h
#   2004/05/18 23:40:46-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/18 14:26:58-07:00 akpm@bix.(none) 
#   Merge http://linux-sound.bkbits.net/linux-sound
#   into bix.(none):/usr/src/bk-alsa
# 
# sound/pcmcia/pdaudiocf/pdaudiocf.c
#   2004/05/18 14:26:55-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/05/18 14:26:55-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# sound/isa/es1688/es1688.c
#   2004/05/18 14:26:55-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/pci_ids.h
#   2004/05/18 14:26:55-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/18 14:25:56-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/18 14:25:53-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/16 01:22:31-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/16 01:22:28-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/14 21:18:25-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/14 21:18:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/11 16:33:03-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/05/11 16:33:00-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/29 15:39:10-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/04/29 15:39:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/26 18:08:46-07:00 akpm@bix.(none) 
#   Merge http://linux-sound.bkbits.net/linux-sound
#   into bix.(none):/usr/src/bk-alsa
# 
# sound/pcmcia/pdaudiocf/pdaudiocf.c
#   2004/04/26 18:08:43-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# sound/isa/wavefront/wavefront_synth.c
#   2004/04/26 18:08:43-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# sound/isa/es1688/es1688.c
#   2004/04/26 18:08:43-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/pci_ids.h
#   2004/04/26 18:08:43-07:00 akpm@bix.(none) +0 -2
#   Auto merged
# 
# ChangeSet
#   2004/04/25 22:42:13-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/04/25 22:42:10-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/16 12:26:24-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/04/16 12:26:21-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/14 18:18:38-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/04/14 18:18:35-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/13 17:03:26-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/04/13 17:03:23-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/12 20:38:27-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-alsa
# 
# include/linux/pci_ids.h
#   2004/04/12 20:38:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/01 14:38:57-08:00 akpm@bix.(none) 
#   x
# 
# include/linux/pci_ids.h
#   2004/04/01 14:38:53-08:00 akpm@bix.(none) +2 -3
#   x
# 
diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
--- a/Documentation/sound/alsa/ALSA-Configuration.txt	2004-06-26 17:13:23 -07:00
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt	2004-06-26 17:13:23 -07:00
@@ -516,6 +516,13 @@
 
     Module for ForteMedia FM801 based PCI soundcards.
 
+    tea575x_tuner       - Enable TEA575x tuner
+                          - 1 = MediaForte 256-PCS
+                          - 2 = MediaForte 256-PCPR
+                          - 3 = MediaForte 64-PCR  
+                          - High 16-bits are video (radio) device number + 1
+                          - example: 0x10002 (MediaForte 256-PCPR, device 1)
+
     Module supports up to 8 cards and autoprobe.
     
   Module snd-gusclassic
@@ -613,7 +620,7 @@
     model       - Use the given board model, one of the following:
 		  delta1010, dio2496, delta66, delta44, audiophile, delta410,
 		  delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
-		  dmx6fire, dsp24, dsp24_71, ez8
+		  dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
     omni	- Omni I/O support for MidiMan M-Audio Delta44/66
     cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
                      in msec resolution, default value is 500 (0.5 sec)
@@ -631,7 +638,8 @@
 			* TerraTec Aureon Sky-5.1, Space-7.1
 
     model       - Use the given board model, one of the following:
-		  revo71, amp2000, prodigy71, aureon51, aureon71
+		  revo71, amp2000, prodigy71, aureon51, aureon71,
+		  k8x800
 
     Module supports up to 8 cards and autoprobe.
 
diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/ac97_codec.h	2004-06-26 17:13:23 -07:00
@@ -441,6 +441,7 @@
 	unsigned short subsystem_vendor;
 	unsigned short subsystem_device;
 	spinlock_t reg_lock;
+	struct semaphore mutex;	/* mutex for AD18xx multi-codecs and paging (2.3) */
 	unsigned short num;	/* number of codec: 0 = primary, 1 = secondary */
 	unsigned short addr;	/* physical address of codec [0-3] */
 	unsigned int id;	/* identification of codec */
@@ -461,7 +462,6 @@
 			unsigned short id[3];		// codec IDs (lower 16-bit word)
 			unsigned short pcmreg[3];	// PCM registers
 			unsigned short codec_cfg[3];	// CODEC_CFG bits
-			struct semaphore mutex;
 		} ad18xx;
 		unsigned int dev_flags;		/* device specific */
 	} spec;
@@ -483,6 +483,10 @@
 static inline int ac97_can_amap(ac97_t * ac97)
 {
 	return (ac97->ext_id & AC97_EI_AMAP) != 0;
+}
+static inline int ac97_can_spdif(ac97_t * ac97)
+{
+	return (ac97->ext_id & AC97_EI_SPDIF) != 0;
 }
 
 /* functions */
diff -Nru a/include/sound/asound.h b/include/sound/asound.h
--- a/include/sound/asound.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/asound.h	2004-06-26 17:13:23 -07:00
@@ -274,6 +274,7 @@
 #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
 #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
 #define SNDRV_PCM_INFO_NONATOMIC_OPS	0x00800000	/* non-atomic prepare callback */
+#define SNDRV_PCM_INFO_MMAP_IOMEM	0x01000000	/* mmap on IO memory */
 
 enum sndrv_pcm_state {
 	SNDRV_PCM_STATE_OPEN = 0,	/* stream is open */
diff -Nru a/include/sound/core.h b/include/sound/core.h
--- a/include/sound/core.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/core.h	2004-06-26 17:13:23 -07:00
@@ -211,12 +211,14 @@
 				 void *private_data);
 #define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
 	snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data)
+#ifdef CONFIG_PCI
 #ifndef SND_PCI_PM_CALLBACKS
 int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
 int snd_card_pci_resume(struct pci_dev *dev);
 #define SND_PCI_PM_CALLBACKS \
 	.suspend = snd_card_pci_suspend,  .resume = snd_card_pci_resume
 #endif
+#endif
 #else
 #define snd_power_lock(card)		do { (void)(card); } while (0)
 #define snd_power_unlock(card)		do { (void)(card); } while (0)
@@ -226,7 +228,9 @@
 #define snd_card_set_pm_callback(card,suspend,resume,data) -EINVAL
 #define snd_card_set_dev_pm_callback(card,suspend,resume,data) -EINVAL
 #define snd_card_set_isa_pm_callback(card,suspend,resume,data) -EINVAL
+#ifdef CONFIG_PCI
 #define SND_PCI_PM_CALLBACKS
+#endif
 #endif
 
 /* device.c */
diff -Nru a/include/sound/emu10k1.h b/include/sound/emu10k1.h
--- a/include/sound/emu10k1.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/emu10k1.h	2004-06-26 17:13:23 -07:00
@@ -1069,6 +1069,15 @@
 /* proc interface */
 int snd_emu10k1_proc_init(emu10k1_t * emu);
 
+/* fx8010 irq handler */
+int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+					    snd_fx8010_irq_handler_t *handler,
+					    unsigned char gpr_running,
+					    void *private_data,
+					    snd_emu10k1_fx8010_irq_t **r_irq);
+int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
+					      snd_emu10k1_fx8010_irq_t *irq);
+
 #endif /* __KERNEL__ */
 
 /*
diff -Nru a/include/sound/pcm.h b/include/sound/pcm.h
--- a/include/sound/pcm.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/pcm.h	2004-06-26 17:13:23 -07:00
@@ -351,7 +351,8 @@
 	unsigned char *dma_area;	/* DMA area */
 	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
 	size_t dma_bytes;		/* size of DMA area */
-	void *dma_private;		/* private DMA data for the memory allocator */
+
+	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
@@ -851,7 +852,7 @@
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
 int snd_pcm_format_width(snd_pcm_format_t format);			/* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);		/* in bits */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format);
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
@@ -892,6 +893,22 @@
 
 int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime);
 
+static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream,
+					      struct snd_dma_buffer *bufp)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	if (bufp) {
+		runtime->dma_buffer_p = bufp;
+		runtime->dma_area = bufp->area;
+		runtime->dma_addr = bufp->addr;
+		runtime->dma_bytes = bufp->bytes;
+	} else {
+		runtime->dma_buffer_p = NULL;
+		runtime->dma_area = NULL;
+		runtime->dma_addr = 0;
+		runtime->dma_bytes = 0;
+	}
+}
 
 /*
  *  Timer interface
@@ -916,7 +933,7 @@
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size);
 int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream);
 
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
+#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
 #define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
 #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
 struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
diff -Nru a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
--- a/include/sound/seq_kernel.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/seq_kernel.h	2004-06-26 17:13:23 -07:00
@@ -168,6 +168,9 @@
 int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned);
 int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data);
 
+/* interface for OSS emulation */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo);
+
 /* port callback routines */
 void snd_port_init_callback(snd_seq_port_callback_t *p);
 snd_seq_port_callback_t *snd_port_alloc_callback(void);
diff -Nru a/include/sound/version.h b/include/sound/version.h
--- a/include/sound/version.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/version.h	2004-06-26 17:13:23 -07:00
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "1.0.4"
-#define CONFIG_SND_DATE " (Mon May 17 14:31:44 2004 UTC)"
+#define CONFIG_SND_VERSION "1.0.5"
+#define CONFIG_SND_DATE " (Sun May 30 10:49:40 2004 UTC)"
diff -Nru a/include/sound/vx_core.h b/include/sound/vx_core.h
--- a/include/sound/vx_core.h	2004-06-26 17:13:23 -07:00
+++ b/include/sound/vx_core.h	2004-06-26 17:13:23 -07:00
@@ -182,6 +182,7 @@
 	/* clock and audio sources */
 	unsigned int audio_source;	/* current audio input source */
 	unsigned int audio_source_target;
+	unsigned int clock_mode;	/* clock mode (VX_CLOCK_MODE_XXX) */
 	unsigned int clock_source;	/* current clock source (INTERNAL_QUARTZ or UER_SYNC) */
 	unsigned int freq;		/* current frequency */
 	unsigned int freq_detected;	/* detected frequency from digital in */
@@ -362,6 +363,13 @@
 enum {
 	INTERNAL_QUARTZ,
 	UER_SYNC
+};
+
+/* clock mode */
+enum {
+	VX_CLOCK_MODE_AUTO,	/* depending on the current audio source */
+	VX_CLOCK_MODE_INTERNAL,	/* fixed to internal quartz */
+	VX_CLOCK_MODE_EXTERNAL	/* fixed to UER sync */
 };
 
 /* SPDIF/UER type */
diff -Nru a/sound/core/memalloc.c b/sound/core/memalloc.c
--- a/sound/core/memalloc.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/memalloc.c	2004-06-26 17:13:23 -07:00
@@ -45,10 +45,14 @@
 #ifndef SNDRV_CARDS
 #define SNDRV_CARDS	8
 #endif
+
+/* FIXME: so far only some PCI devices have the preallocation table */
+#ifdef CONFIG_PCI
 static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 static int boot_devs;
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
+#endif
 
 /*
  */
diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
--- a/sound/core/oss/pcm_oss.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/oss/pcm_oss.c	2004-06-26 17:13:23 -07:00
@@ -1177,10 +1177,11 @@
 	snd_pcm_substream_t *substream;
 	int err;
 	int direct;
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	unsigned int formats = 0;
 	snd_mask_t format_mask;
 	int fmt;
+
 	if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
 		return err;
 	if (atomic_read(&substream->runtime->mmap_count)) {
@@ -1194,10 +1195,14 @@
 		       AFMT_S16_LE | AFMT_S16_BE |
 		       AFMT_S8 | AFMT_U16_LE |
 		       AFMT_U16_BE;
-	_snd_pcm_hw_params_any(&params);
-	err = snd_pcm_hw_refine(substream, &params);
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	_snd_pcm_hw_params_any(params);
+	err = snd_pcm_hw_refine(substream, params);
+	format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 
+	kfree(params);
 	snd_assert(err >= 0, return err);
-	format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT); 
 	for (fmt = 0; fmt < 32; ++fmt) {
 		if (snd_mask_test(&format_mask, fmt)) {
 			int f = snd_pcm_oss_format_to(fmt);
@@ -2280,7 +2285,7 @@
 				   snd_info_buffer_t * buffer)
 {
 	snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
-	char line[512], str[32], task_name[32], *ptr;
+	char line[256], str[32], task_name[32], *ptr;
 	int idx1;
 	snd_pcm_oss_setup_t *setup, *setup1, template;
 
diff -Nru a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
--- a/sound/core/oss/pcm_plugin.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/oss/pcm_plugin.c	2004-06-26 17:13:23 -07:00
@@ -846,41 +846,31 @@
 			 size_t samples, int format)
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
-	char *dst;
+	unsigned char *dst;
 	unsigned int dst_step;
 	int width;
-	u_int64_t silence;
+	const unsigned char *silence;
 	if (!dst_area->addr)
 		return 0;
 	dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
 	width = snd_pcm_format_physical_width(format);
+	if (width <= 0)
+		return -EINVAL;
+	if (dst_area->step == (unsigned int) width && width >= 8)
+		return snd_pcm_format_set_silence(format, dst, samples);
 	silence = snd_pcm_format_silence_64(format);
-	if (dst_area->step == (unsigned int) width) {
-		size_t dwords = samples * width / 64;
-		u_int64_t *dst64 = (u_int64_t *)dst;
-
-		samples -= dwords * 64 / width;
-		while (dwords-- > 0)
-			*dst64++ = silence;
-		if (samples == 0)
-			return 0;
-		dst = (char *)dst64;
-	}
+	if (! silence)
+		return -EINVAL;
 	dst_step = dst_area->step / 8;
-	switch (width) {
-	case 4: {
-		u_int8_t s0 = silence & 0xf0;
-		u_int8_t s1 = silence & 0x0f;
+	if (width == 4) {
+		/* Ima ADPCM */
 		int dstbit = dst_area->first % 8;
 		int dstbit_step = dst_area->step % 8;
 		while (samples-- > 0) {
-			if (dstbit) {
+			if (dstbit)
 				*dst &= 0xf0;
-				*dst |= s1;
-			} else {
+			else
 				*dst &= 0x0f;
-				*dst |= s0;
-			}
 			dst += dst_step;
 			dstbit += dstbit_step;
 			if (dstbit == 8) {
@@ -888,41 +878,12 @@
 				dstbit = 0;
 			}
 		}
-		break;
-	}
-	case 8: {
-		u_int8_t sil = silence;
-		while (samples-- > 0) {
-			*dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 16: {
-		u_int16_t sil = silence;
-		while (samples-- > 0) {
-			*(u_int16_t*)dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 32: {
-		u_int32_t sil = silence;
-		while (samples-- > 0) {
-			*(u_int32_t*)dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 64: {
+	} else {
+		width /= 8;
 		while (samples-- > 0) {
-			*(u_int64_t*)dst = silence;
+			memcpy(dst, silence, width);
 			dst += dst_step;
 		}
-		break;
-	}
-	default:
-		snd_BUG();
 	}
 	return 0;
 }
@@ -942,18 +903,18 @@
 	if (!dst_area->addr)
 		return 0;
 	width = snd_pcm_format_physical_width(format);
+	if (width <= 0)
+		return -EINVAL;
 	if (src_area->step == (unsigned int) width &&
-	    dst_area->step == (unsigned int) width) {
+	    dst_area->step == (unsigned int) width && width >= 8) {
 		size_t bytes = samples * width / 8;
-		samples -= bytes * 8 / width;
 		memcpy(dst, src, bytes);
-		if (samples == 0)
-			return 0;
+		return 0;
 	}
 	src_step = src_area->step / 8;
 	dst_step = dst_area->step / 8;
-	switch (width) {
-	case 4: {
+	if (width == 4) {
+		/* Ima ADPCM */
 		int srcbit = src_area->first % 8;
 		int srcbit_step = src_area->step % 8;
 		int dstbit = dst_area->first % 8;
@@ -963,12 +924,11 @@
 			if (srcbit)
 				srcval = *src & 0x0f;
 			else
-				srcval = *src & 0xf0;
+				srcval = (*src & 0xf0) >> 4;
 			if (dstbit)
-				*dst &= 0xf0;
+				*dst = (*dst & 0xf0) | srcval;
 			else
-				*dst &= 0x0f;
-			*dst |= srcval;
+				*dst = (*dst & 0x0f) | (srcval << 4);
 			src += src_step;
 			srcbit += srcbit_step;
 			if (srcbit == 8) {
@@ -982,42 +942,13 @@
 				dstbit = 0;
 			}
 		}
-		break;
-	}
-	case 8: {
-		while (samples-- > 0) {
-			*dst = *src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 16: {
+	} else {
+		width /= 8;
 		while (samples-- > 0) {
-			*(u_int16_t*)dst = *(u_int16_t*)src;
+			memcpy(dst, src, width);
 			src += src_step;
 			dst += dst_step;
 		}
-		break;
-	}
-	case 32: {
-		while (samples-- > 0) {
-			*(u_int32_t*)dst = *(u_int32_t*)src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 64: {
-		while (samples-- > 0) {
-			*(u_int64_t*)dst = *(u_int64_t*)src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	default:
-		snd_BUG();
 	}
 	return 0;
 }
diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
--- a/sound/core/pcm_memory.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/pcm_memory.c	2004-06-26 17:13:23 -07:00
@@ -314,31 +314,35 @@
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
 {
 	snd_pcm_runtime_t *runtime;
-	struct snd_dma_buffer dmab;
+	struct snd_dma_buffer *dmab = NULL;
 
 	snd_assert(substream->dma_device.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
 	snd_assert(substream != NULL, return -EINVAL);
 	runtime = substream->runtime;
-	snd_assert(runtime != NULL, return -EINVAL);	
+	snd_assert(runtime != NULL, return -EINVAL);
 
-	if (runtime->dma_area != NULL) {
+	if (runtime->dma_buffer_p) {
 		/* perphaps, we might free the large DMA memory region
 		   to save some space here, but the actual solution
 		   costs us less time */
-		if (runtime->dma_bytes >= size)
+		if (runtime->dma_buffer_p->bytes >= size) {
+			runtime->dma_bytes = size;
 			return 0;	/* ok, do not change */
+		}
 		snd_pcm_lib_free_pages(substream);
 	}
 	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
-		dmab = substream->dma_buffer; /* use the pre-allocated buffer */
+		dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
 	} else {
-		memset(&dmab, 0, sizeof(dmab)); /* allocate a new buffer */
-		if (snd_dma_alloc_pages(&substream->dma_device, size, &dmab) < 0)
+		dmab = snd_kcalloc(sizeof(*dmab), GFP_KERNEL);
+		if (! dmab)
+			return -ENOMEM;
+		if (snd_dma_alloc_pages(&substream->dma_device, size, dmab) < 0) {
+			kfree(dmab);
 			return -ENOMEM;
+		}
 	}
-	runtime->dma_area = dmab.area;
-	runtime->dma_addr = dmab.addr;
-	runtime->dma_private = dmab.private_data;
+	snd_pcm_set_runtime_buffer(substream, dmab);
 	runtime->dma_bytes = size;
 	return 1;			/* area was changed */
 }
@@ -360,34 +364,11 @@
 	snd_assert(runtime != NULL, return -EINVAL);
 	if (runtime->dma_area == NULL)
 		return 0;
-	if (runtime->dma_area != substream->dma_buffer.area) {
+	if (runtime->dma_buffer_p != &substream->dma_buffer) {
 		/* it's a newly allocated buffer.  release it now. */
-		struct snd_dma_buffer dmab;
-		memset(&dmab, 0, sizeof(dmab));
-		dmab.area = runtime->dma_area;
-		dmab.addr = runtime->dma_addr;
-		dmab.bytes = runtime->dma_bytes;
-		dmab.private_data = runtime->dma_private;
-		snd_dma_free_pages(&substream->dma_device, &dmab);
+		snd_dma_free_pages(&substream->dma_device, runtime->dma_buffer_p);
+		kfree(runtime->dma_buffer_p);
 	}
-	runtime->dma_area = NULL;
-	runtime->dma_addr = 0UL;
-	runtime->dma_bytes = 0;
-	runtime->dma_private = NULL;
+	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
 }
-
-#ifndef MODULE
-
-/* format is: snd-pcm=preallocate_dma,maximum_substreams */
-
-static int __init alsa_pcm_setup(char *str)
-{
-	(void)(get_option(&str,&preallocate_dma) == 2 &&
-	       get_option(&str,&maximum_substreams) == 2);
-	return 1;
-}
-
-__setup("snd-pcm=", alsa_pcm_setup);
-
-#endif /* ifndef MODULE */
diff -Nru a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
--- a/sound/core/pcm_misc.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/pcm_misc.c	2004-06-26 17:13:23 -07:00
@@ -23,12 +23,169 @@
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
-#define bswap_16 swab16
-#define bswap_32 swab32
-#define bswap_64 swab64
 #define SND_PCM_FORMAT_UNKNOWN (-1)
-#define snd_enum_to_int(v) (v)
-#define snd_int_to_enum(v) (v)
+
+struct pcm_format_data {
+	char width;	/* bit width */
+	char phys;	/* physical bit width */
+	char le;	/* 0 = big-endian, 1 = little-endian, -1 = others */
+	char signd;	/* 0 = unsigned, 1 = signed, -1 = others */
+	unsigned char silence[8];	/* silence data to fill */
+};
+
+static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
+	[SNDRV_PCM_FORMAT_S8] = {
+		.width = 8, .phys = 8, .le = -1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U8] = {
+		.width = 8, .phys = 8, .le = -1, .signd = 0,
+		.silence = { 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_S16_LE] = {
+		.width = 16, .phys = 16, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S16_BE] = {
+		.width = 16, .phys = 16, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U16_LE] = {
+		.width = 16, .phys = 16, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U16_BE] = {
+		.width = 16, .phys = 16, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S24_LE] = {
+		.width = 24, .phys = 32, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S24_BE] = {
+		.width = 24, .phys = 32, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U24_LE] = {
+		.width = 24, .phys = 32, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U24_BE] = {
+		.width = 24, .phys = 32, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S32_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S32_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U32_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U32_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_FLOAT_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT64_LE] = {
+		.width = 64, .phys = 64, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT64_BE] = {
+		.width = 64, .phys = 64, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_MU_LAW] = {
+		.width = 8, .phys = 8, .le = -1, .signd = -1,
+		.silence = { 0x7f },
+	},
+	[SNDRV_PCM_FORMAT_A_LAW] = {
+		.width = 8, .phys = 8, .le = -1, .signd = -1,
+		.silence = { 0x55 },
+	},
+	[SNDRV_PCM_FORMAT_IMA_ADPCM] = {
+		.width = 4, .phys = 4, .le = -1, .signd = -1,
+		.silence = {},
+	},
+	/* FIXME: the following three formats are not defined properly yet */
+	[SNDRV_PCM_FORMAT_MPEG] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_GSM] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_SPECIAL] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_S24_3LE] = {
+		.width = 24, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S24_3BE] = {
+		.width = 24, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U24_3LE] = {
+		.width = 24, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U24_3BE] = {
+		.width = 24, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S20_3LE] = {
+		.width = 20, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S20_3BE] = {
+		.width = 20, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U20_3LE] = {
+		.width = 20, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x08 },
+	},
+	[SNDRV_PCM_FORMAT_U20_3BE] = {
+		.width = 20, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x08, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S18_3LE] = {
+		.width = 18, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S18_3BE] = {
+		.width = 18, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U18_3LE] = {
+		.width = 18, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x02 },
+	},
+	[SNDRV_PCM_FORMAT_U18_3BE] = {
+		.width = 18, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x02, 0x00, 0x00 },
+	},
+};
+
 
 /**
  * snd_pcm_format_signed - Check the PCM format is signed linear
@@ -39,38 +196,12 @@
  */
 int snd_pcm_format_signed(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-		return 1;
-	case SNDRV_PCM_FORMAT_U8:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].signd) < 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -110,42 +241,12 @@
  */
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 1;
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].le) < 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -190,55 +291,12 @@
  */
 int snd_pcm_format_width(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return 8;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 16;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 18;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 20;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 24;
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return 64;
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 8;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		return 4;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].width) == 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -250,52 +308,12 @@
  */
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return 8;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 16;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 24;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return 64;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 8;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		return 4;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].phys) == 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -307,216 +325,25 @@
  */
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return samples;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return samples * 2;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return samples * 3;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-		return samples * 4;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return samples * 8;
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return samples * 4;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return samples;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		if (samples & 1)
-			return -EINVAL;
-		return samples / 2;
-	default:
+	int phys_width = snd_pcm_format_physical_width(format);
+	if (phys_width < 0)
 		return -EINVAL;
-	}
+	return samples * phys_width / 8;
 }
 
 /**
- * snd_pcm_format_silence_64 - return the silent data in 64bit integer
+ * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
  * @format: the format to check
  *
- * Returns the silent data in 64bit integer for the given format.
+ * Returns the format pattern to fill or NULL if error.
  */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-		return 0;
-	case SNDRV_PCM_FORMAT_U8:
-		return 0x8080808080808080ULL;
-#ifdef SNDRV_LITTLE_ENDIAN
-	case SNDRV_PCM_FORMAT_U16_LE:
-		return 0x8000800080008000ULL;
-	case SNDRV_PCM_FORMAT_U24_LE:
-		return 0x0080000000800000ULL;
-	case SNDRV_PCM_FORMAT_U32_LE:
-		return 0x8000000080000000ULL;
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 0x0080008000800080ULL;
-	case SNDRV_PCM_FORMAT_U24_BE:
-		return 0x0000800000008000ULL;
-	case SNDRV_PCM_FORMAT_U32_BE:
-		return 0x0000008000000080ULL;
-	case SNDRV_PCM_FORMAT_U24_3LE:
-		return 0x0000800000800000ULL;
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 0x0080000080000080ULL;
-	case SNDRV_PCM_FORMAT_U20_3LE:
-		return 0x0000080000080000ULL;
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 0x0008000008000008ULL;
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 0x0000020000020000ULL;
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0x0002000002000002ULL;
-#else
-	case SNDRV_PCM_FORMAT_U16_LE:
-		return 0x0080008000800080ULL;
-	case SNDRV_PCM_FORMAT_U24_LE:
-		return 0x0000800000008000ULL;
-	case SNDRV_PCM_FORMAT_U32_LE:
-		return 0x0000008000000080ULL;
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 0x8000800080008000ULL;
-	case SNDRV_PCM_FORMAT_U24_BE:
-		return 0x0080000000800000ULL;
-	case SNDRV_PCM_FORMAT_U32_BE:
-		return 0x8000000080000000ULL;
-	case SNDRV_PCM_FORMAT_U24_3LE:
-		return 0x0080000080000080ULL;
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 0x0000800000800000ULL;
-	case SNDRV_PCM_FORMAT_U20_3LE:
-		return 0x0008000008000008ULL;
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 0x0000080000080000ULL;
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 0x0002000002000002ULL;
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0x0000020000020000ULL;
-#endif
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	{
-		union {
-			float f;
-			u_int32_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return u.i;
-#else
-		return bswap_32(u.i);
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	{
-		union {
-			double f;
-			u_int64_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return u.i;
-#else
-		return bswap_64(u.i);
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT_BE:		
-	{
-		union {
-			float f;
-			u_int32_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return bswap_32(u.i);
-#else
-		return u.i;
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-	{
-		union {
-			double f;
-			u_int64_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return bswap_64(u.i);
-#else
-		return u.i;
-#endif
-	}
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 0;	
-	case SNDRV_PCM_FORMAT_MU_LAW:
-		return 0x7f7f7f7f7f7f7f7fULL;
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 0x5555555555555555ULL;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:	/* special case */
-	case SNDRV_PCM_FORMAT_MPEG:
-	case SNDRV_PCM_FORMAT_GSM:
-	case SNDRV_PCM_FORMAT_SPECIAL:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
-{
-	return (u_int32_t)snd_pcm_format_silence_64(format);
-}
-
-u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
-{
-	return (u_int16_t)snd_pcm_format_silence_64(format);
-}
-
-u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
-{
-	return (u_int8_t)snd_pcm_format_silence_64(format);
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+		return NULL;
+	if (! pcm_formats[format].phys)
+		return NULL;
+	return pcm_formats[format].silence;
 }
 
 /**
@@ -531,99 +358,73 @@
  */
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
 {
+	int width;
+	unsigned char *dst, *pat;
+
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+		return -EINVAL;
 	if (samples == 0)
 		return 0;
-	switch (snd_pcm_format_width(format)) {
-	case 4: {
-		u_int8_t silence = snd_pcm_format_silence_64(format);
-		unsigned int samples1;
-		if (samples % 2 != 0)
-			return -EINVAL;
-		samples1 = samples / 2;
-		memset(data, silence, samples1);
-		break;
+	width = pcm_formats[format].phys; /* physical width */
+	pat = pcm_formats[format].silence;
+	if (! width)
+		return -EINVAL;
+	/* signed or 1 byte data */
+	if (pcm_formats[format].signd == 1 || width <= 8) {
+		unsigned int bytes = samples * width / 8;
+		memset(data, *pat, bytes);
+		return 0;
 	}
-	case 8: {
-		u_int8_t silence = snd_pcm_format_silence_64(format);
-		memset(data, silence, samples);
-		break;
+	/* non-zero samples, fill using a loop */
+	width /= 8;
+	dst = data;
+#if 0
+	while (samples--) {
+		memcpy(dst, pat, width);
+		dst += width;
 	}
-	case 16: {
-		u_int16_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 2);
-		else {
-			u_int16_t *data16 = data;
-			while (samples-- > 0)
-				*data16++ = silence;
+#else
+	/* a bit optimization for constant width */
+	switch (width) {
+	case 2:
+		while (samples--) {
+			memcpy(dst, pat, 2);
+			dst += 2;
 		}
 		break;
-	}
-	case 24: {
-		u_int32_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 3);
-		else {
-			while (samples-- > 0) {
-				u_int8_t *data8 = data;
-#ifdef SNDRV_LITTLE_ENDIAN
-				*data8++ = silence >> 0;
-				*data8++ = silence >> 8;
-				*data8++ = silence >> 16;
-#else
-				*data8++ = silence >> 16;
-				*data8++ = silence >> 8;
-				*data8++ = silence >> 0;
-#endif
-			}
+	case 3:
+		while (samples--) {
+			memcpy(dst, pat, 3);
+			dst += 3;
 		}
 		break;
-	}
-	case 32: {
-		u_int32_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 4);
-		else {
-			u_int32_t *data32 = data;
-			while (samples-- > 0)
-				*data32++ = silence;
+	case 4:
+		while (samples--) {
+			memcpy(dst, pat, 4);
+			dst += 4;
 		}
 		break;
-	}
-	case 64: {
-		u_int64_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 8);
-		else {
-			u_int64_t *data64 = data;
-			while (samples-- > 0)
-				*data64++ = silence;
+	case 8:
+		while (samples--) {
+			memcpy(dst, pat, 8);
+			dst += 8;
 		}
 		break;
 	}
-	default:
-		return -EINVAL;
-	}
+#endif
 	return 0;
 }
 
-static int linear_formats[4*2*2] = {
-	SNDRV_PCM_FORMAT_S8,
-	SNDRV_PCM_FORMAT_S8,
-	SNDRV_PCM_FORMAT_U8,
-	SNDRV_PCM_FORMAT_U8,
-	SNDRV_PCM_FORMAT_S16_LE,
-	SNDRV_PCM_FORMAT_S16_BE,
-	SNDRV_PCM_FORMAT_U16_LE,
-	SNDRV_PCM_FORMAT_U16_BE,
-	SNDRV_PCM_FORMAT_S24_LE,
-	SNDRV_PCM_FORMAT_S24_BE,
-	SNDRV_PCM_FORMAT_U24_LE,
-	SNDRV_PCM_FORMAT_U24_BE,
-	SNDRV_PCM_FORMAT_S32_LE,
-	SNDRV_PCM_FORMAT_S32_BE,
-	SNDRV_PCM_FORMAT_U32_LE,
-	SNDRV_PCM_FORMAT_U32_BE
+/* [width][unsigned][bigendian] */
+static int linear_formats[4][2][2] = {
+	{{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
+	 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
+	{{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
+	 {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
+	{{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
+	 {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
+	{{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
+	 {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
 };
 
 /**
@@ -636,23 +437,12 @@
  */
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
 {
-	switch (width) {
-	case 8:
-		width = 0;
-		break;
-	case 16:
-		width = 1;
-		break;
-	case 24:
-		width = 2;
-		break;
-	case 32:
-		width = 3;
-		break;
-	default:
+	if (width & 7)
 		return SND_PCM_FORMAT_UNKNOWN;
-	}
-	return snd_int_to_enum(((int(*)[2][2])linear_formats)[width][!!unsignd][!!big_endian]);
+	width = (width / 8) - 1;
+	if (width < 0 || width >= 4)
+		return SND_PCM_FORMAT_UNKNOWN;
+	return linear_formats[width][!!unsignd][!!big_endian];
 }
 
 /**
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/pcm_native.c	2004-06-26 17:13:23 -07:00
@@ -304,13 +304,25 @@
 
 static int snd_pcm_hw_refine_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
 {
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	int err;
-	if (copy_from_user(&params, _params, sizeof(params)))
-		return -EFAULT;
-	err = snd_pcm_hw_refine(substream, &params);
-	if (copy_to_user(_params, &params, sizeof(params)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(params, _params, sizeof(*params))) {
+		err = -EFAULT;
+		goto out;
+	}
+	err = snd_pcm_hw_refine(substream, params);
+	if (copy_to_user(_params, params, sizeof(*params))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
 	return err;
 }
 
@@ -408,13 +420,25 @@
 
 static int snd_pcm_hw_params_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
 {
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	int err;
-	if (copy_from_user(&params, _params, sizeof(params)))
-		return -EFAULT;
-	err = snd_pcm_hw_params(substream, &params);
-	if (copy_to_user(_params, &params, sizeof(params)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(params, _params, sizeof(*params))) {
+		err = -EFAULT;
+		goto out;
+	}
+	err = snd_pcm_hw_params(substream, params);
+	if (copy_to_user(_params, params, sizeof(*params))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
 	return err;
 }
 
@@ -3009,6 +3033,12 @@
 	.nopage =	snd_pcm_mmap_data_nopage,
 };
 
+static struct vm_operations_struct snd_pcm_vm_ops_data_mmio =
+{
+	.open =		snd_pcm_mmap_data_open,
+	.close =	snd_pcm_mmap_data_close,
+};
+
 int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
 		      struct vm_area_struct *area)
 {
@@ -3044,6 +3074,14 @@
 	area->vm_ops = &snd_pcm_vm_ops_data;
 	area->vm_private_data = substream;
 	area->vm_flags |= VM_RESERVED;
+	if (runtime->hw.info & SNDRV_PCM_INFO_MMAP_IOMEM) {
+		area->vm_ops = &snd_pcm_vm_ops_data_mmio;
+		area->vm_flags |= VM_IO;
+		if (io_remap_page_range(area, area->vm_start,
+					runtime->dma_addr + offset,
+					size, area->vm_page_prot))
+			return -EAGAIN;
+	}
 	atomic_inc(&runtime->mmap_count);
 	return 0;
 }
@@ -3133,31 +3171,68 @@
 
 static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
 {
-	snd_pcm_hw_params_t params;
-	struct sndrv_pcm_hw_params_old oparams;
+	snd_pcm_hw_params_t *params;
+	struct sndrv_pcm_hw_params_old *oparams = NULL;
 	int err;
-	if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
-		return -EFAULT;
-	snd_pcm_hw_convert_from_old_params(&params, &oparams);
-	err = snd_pcm_hw_refine(substream, &params);
-	snd_pcm_hw_convert_to_old_params(&oparams, &params);
-	if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
+	if (!oparams) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
+		err = -EFAULT;
+		goto out;
+	}
+	snd_pcm_hw_convert_from_old_params(params, oparams);
+	err = snd_pcm_hw_refine(substream, params);
+	snd_pcm_hw_convert_to_old_params(oparams, params);
+	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
+	kfree(oparams);
 	return err;
 }
 
 static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
 {
-	snd_pcm_hw_params_t params;
-	struct sndrv_pcm_hw_params_old oparams;
+	snd_pcm_hw_params_t *params;
+	struct sndrv_pcm_hw_params_old *oparams = NULL;
 	int err;
-	if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
-		return -EFAULT;
-	snd_pcm_hw_convert_from_old_params(&params, &oparams);
-	err = snd_pcm_hw_params(substream, &params);
-	snd_pcm_hw_convert_to_old_params(&oparams, &params);
-	if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
+	if (!oparams) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
+		err = -EFAULT;
+		goto out;
+	}
+	snd_pcm_hw_convert_from_old_params(params, oparams);
+	err = snd_pcm_hw_params(substream, params);
+	snd_pcm_hw_convert_to_old_params(oparams, params);
+	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
+	kfree(oparams);
 	return err;
 }
 
diff -Nru a/sound/core/seq/Makefile b/sound/core/seq/Makefile
--- a/sound/core/seq/Makefile	2004-06-26 17:13:23 -07:00
+++ b/sound/core/seq/Makefile	2004-06-26 17:13:23 -07:00
@@ -19,9 +19,6 @@
 snd-seq-dummy-objs := seq_dummy.o
 snd-seq-virmidi-objs := seq_virmidi.o
 
-RAWMIDI_OBJS = snd-seq-midi.o snd-seq-midi-event.o
-OPL3_OBJS = snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
-
 #
 # this function returns:
 #   "m" - CONFIG_SND_SEQUENCER is m
@@ -38,53 +35,8 @@
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
-obj-$(call sequencer,$(CONFIG_SND_SERIAL_U16550)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_MTPAV)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_MPU401)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALS100)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AZT2320)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AZT3328)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_DT019X)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES18XX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPL3SA2)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4231)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4232)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4236)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1688)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_AD1848)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_CS4231)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI93X)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SB8)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SB16)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += $(RAWMIDI_OBJS) $(OPL3_OBJS) snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_ES968)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_WAVEFRONT)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SSCAPE)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALS4000)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CMIPCI)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4281)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ENS1370)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ENS1371)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1938)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1968)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_FM801)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ICE1712)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ICE1724)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTEL8X0)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_VIA82XX)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALI5451)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS46XX)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += $(RAWMIDI_OBJS) snd-seq-midi-emul.o snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += $(RAWMIDI_OBJS) snd-seq-midi-emul.o snd-seq-instr.o
-obj-$(call sequencer,$(CONFIG_SND_YMFPCI)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_USB_AUDIO)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_HDSP)) += $(RAWMIDI_OBJS)
-
-obj-m := $(sort $(obj-m))
+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 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 -Nru a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
--- a/sound/core/seq/instr/Makefile	2004-06-26 17:13:23 -07:00
+++ b/sound/core/seq/instr/Makefile	2004-06-26 17:13:23 -07:00
@@ -17,35 +17,7 @@
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 # Toplevel Module Dependency
-obj-$(call sequencer,$(CONFIG_SND_ALS100)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AZT2320)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AZT3328)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_DT019X)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES18XX)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPL3SA2)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4232)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4236)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES1688)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_AD1848)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_CS4231)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI93X)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SB8)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SB16)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_WAVEFRONT)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ALS4000)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CMIPCI)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4281)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES1938)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_FM801)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += snd-ainstr-fm.o
+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
 obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_YMFPCI)) += snd-ainstr-fm.o
-
-obj-m := $(sort $(obj-m))
diff -Nru a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c
--- a/sound/core/seq/oss/seq_oss_ioctl.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/seq/oss/seq_oss_ioctl.c	2004-06-26 17:13:23 -07:00
@@ -28,16 +28,54 @@
 #include "seq_oss_midi.h"
 #include "seq_oss_event.h"
 
+static int snd_seq_oss_synth_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	struct synth_info info;
+
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+	if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
+		return -EINVAL;
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_seq_oss_midi_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	struct midi_info info;
+
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+	if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
+		return -EINVAL;
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_seq_oss_oob_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	unsigned char ev[8];
+	snd_seq_event_t tmpev;
+
+	if (copy_from_user(ev, arg, 8))
+		return -EFAULT;
+	memset(&tmpev, 0, sizeof(tmpev));
+	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
+	tmpev.time.tick = 0;
+	if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
+		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
+	}
+	return 0;
+}
+
 int
 snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
 {
 	int dev, val;
-	struct synth_info inf;
-	struct midi_info minf;
-	unsigned char ev[8];
 	void __user *arg = (void __user *)carg;
 	int __user *p = arg;
-	snd_seq_event_t tmpev;
 
 	switch (cmd) {
 	case SNDCTL_TMR_TIMEBASE:
@@ -124,35 +162,15 @@
 	case SNDCTL_SYNTH_INFO:
 	case SNDCTL_SYNTH_ID:
 		debug_printk(("synth info\n"));
-		if (copy_from_user(&inf, arg, sizeof(inf)))
-			return -EFAULT;
-		if (snd_seq_oss_synth_make_info(dp, inf.device, &inf) < 0)
-			return -EINVAL;
-		if (copy_to_user(arg, &inf, sizeof(inf)))
-			return -EFAULT;
-		return 0;
+		return snd_seq_oss_synth_info_user(dp, arg);
 
 	case SNDCTL_SEQ_OUTOFBAND:
-		debug_printk(("out of bound\n"));
-		if (copy_from_user(ev, arg, 8))
-			return -EFAULT;
-		memset(&tmpev, 0, sizeof(tmpev));
-		snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
-		tmpev.time.tick = 0;
-		if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
-			snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
-		}
-		return 0;
+		debug_printk(("out of band\n"));
+		return snd_seq_oss_oob_user(dp, arg);
 
 	case SNDCTL_MIDI_INFO:
 		debug_printk(("midi info\n"));
-		if (copy_from_user(&minf, arg, sizeof(minf)))
-			return -EFAULT;
-		if (snd_seq_oss_midi_make_info(dp, minf.device, &minf) < 0)
-			return -EINVAL;
-		if (copy_to_user(arg, &minf, sizeof(minf)))
-			return -EFAULT;
-		return 0;
+		return snd_seq_oss_midi_info_user(dp, arg);
 
 	case SNDCTL_SEQ_THRESHOLD:
 		debug_printk(("threshold\n"));
diff -Nru a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
--- a/sound/core/seq/oss/seq_oss_timer.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/seq/oss/seq_oss_timer.c	2004-06-26 17:13:23 -07:00
@@ -168,7 +168,7 @@
 	tmprec.queue = dp->queue;
 	tmprec.ppq = timer->ppq;
 	tmprec.tempo = timer->tempo;
-	snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, &tmprec);
+	snd_seq_set_queue_tempo(dp->cseq, &tmprec);
 
 	send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
 	timer->running = 1;
diff -Nru a/sound/core/seq/seq.c b/sound/core/seq/seq.c
--- a/sound/core/seq/seq.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/seq/seq.c	2004-06-26 17:13:23 -07:00
@@ -133,6 +133,7 @@
 EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
 EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
 EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
+EXPORT_SYMBOL(snd_seq_set_queue_tempo);
   /* seq_memory.c */
 EXPORT_SYMBOL(snd_seq_expand_var_event);
 EXPORT_SYMBOL(snd_seq_dump_var_event);
diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
--- a/sound/core/seq/seq_clientmgr.c	2004-06-26 17:13:23 -07:00
+++ b/sound/core/seq/seq_clientmgr.c	2004-06-26 17:13:23 -07:00
@@ -1694,6 +1694,13 @@
 
 
 /* SET_QUEUE_TEMPO ioctl() */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo)
+{
+	if (!snd_seq_queue_check_access(tempo->queue, client))
+		return -EPERM;
+	return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
+}
+
 static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
 {
 	int result;
@@ -1702,15 +1709,8 @@
 	if (copy_from_user(&tempo, arg, sizeof(tempo)))
 		return -EFAULT;
 
-	if (snd_seq_queue_check_access(tempo.queue, client->number)) {
-		result = snd_seq_queue_timer_set_tempo(tempo.queue, client->number, &tempo);
-		if (result < 0)
-			return result;
-	} else {
-		return -EPERM;
-	}	
-
-	return 0;
+	result = snd_seq_set_queue_tempo(client->number, &tempo);
+	return result < 0 ? result : 0;
 }
 
 
diff -Nru a/sound/drivers/dummy.c b/sound/drivers/dummy.c
--- a/sound/drivers/dummy.c	2004-06-26 17:13:23 -07:00
+++ b/sound/drivers/dummy.c	2004-06-26 17:13:23 -07:00
@@ -180,20 +180,6 @@
 static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
 
-static int snd_card_dummy_playback_ioctl(snd_pcm_substream_t * substream,
-				         unsigned int cmd,
-				         void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
-static int snd_card_dummy_capture_ioctl(snd_pcm_substream_t * substream,
-					unsigned int cmd,
-					void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -342,6 +328,17 @@
 	snd_magic_kfree(dpcm);
 }
 
+static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream,
+				    snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_card_dummy_hw_free(snd_pcm_substream_t * substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
 static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -351,10 +348,6 @@
 	dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
-	if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
-		snd_magic_kfree(dpcm);
-		return -ENOMEM;
-	}
 	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
@@ -386,11 +379,6 @@
 	dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
-	if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
-		snd_magic_kfree(dpcm);
-		return -ENOMEM;
-	}
-	memset(runtime->dma_area, 0, runtime->dma_bytes);
 	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
@@ -415,24 +403,20 @@
 
 static int snd_card_dummy_playback_close(snd_pcm_substream_t * substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-
-	snd_free_pages(runtime->dma_area, runtime->dma_bytes);
 	return 0;
 }
 
 static int snd_card_dummy_capture_close(snd_pcm_substream_t * substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-
-	snd_free_pages(runtime->dma_area, runtime->dma_bytes);
 	return 0;
 }
 
 static snd_pcm_ops_t snd_card_dummy_playback_ops = {
 	.open =			snd_card_dummy_playback_open,
 	.close =		snd_card_dummy_playback_close,
-	.ioctl =		snd_card_dummy_playback_ioctl,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_dummy_hw_params,
+	.hw_free =		snd_card_dummy_hw_free,
 	.prepare =		snd_card_dummy_playback_prepare,
 	.trigger =		snd_card_dummy_playback_trigger,
 	.pointer =		snd_card_dummy_playback_pointer,
@@ -441,7 +425,9 @@
 static snd_pcm_ops_t snd_card_dummy_capture_ops = {
 	.open =			snd_card_dummy_capture_open,
 	.close =		snd_card_dummy_capture_close,
-	.ioctl =		snd_card_dummy_capture_ioctl,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_dummy_hw_params,
+	.hw_free =		snd_card_dummy_hw_free,
 	.prepare =		snd_card_dummy_capture_prepare,
 	.trigger =		snd_card_dummy_capture_trigger,
 	.pointer =		snd_card_dummy_capture_pointer,
@@ -459,6 +445,9 @@
 	pcm->private_data = dummy;
 	pcm->info_flags = 0;
 	strcpy(pcm->name, "Dummy PCM");
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+					      snd_dma_continuous_data(GFP_KERNEL),
+					      0, 64*1024);
 	return 0;
 }
 
diff -Nru a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile
--- a/sound/drivers/opl4/Makefile	2004-06-26 17:13:23 -07:00
+++ b/sound/drivers/opl4/Makefile	2004-06-26 17:13:23 -07:00
@@ -15,4 +15,4 @@
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o
-obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
\ No newline at end of file
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
diff -Nru a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
--- a/sound/drivers/vx/vx_core.c	2004-06-26 17:13:23 -07:00
+++ b/sound/drivers/vx/vx_core.c	2004-06-26 17:13:23 -07:00
@@ -572,6 +572,7 @@
 	if (cold_reset) {
 		chip->audio_source_target = chip->audio_source;
 		chip->clock_source = INTERNAL_QUARTZ;
+		chip->clock_mode = VX_CLOCK_MODE_AUTO;
 		chip->freq = 48000;
 		chip->uer_detected = VX_UER_MODE_NOT_PRESENT;
 		chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -606,6 +607,7 @@
 	vx_core_t *chip = snd_magic_cast(vx_core_t, entry->private_data, return);
 	static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
 	static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
+	static char *clock_mode[] = { "Auto", "Internal", "External" };
 	static char *clock_src[] = { "Internal", "External" };
 	static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
 	
@@ -629,6 +631,7 @@
 	snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?
 		    audio_src_vxp[chip->audio_source] :
 		    audio_src_vx2[chip->audio_source]);
+	snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);
 	snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);
 	snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
 	snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
diff -Nru a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
--- a/sound/drivers/vx/vx_mixer.c	2004-06-26 17:13:23 -07:00
+++ b/sound/drivers/vx/vx_mixer.c	2004-06-26 17:13:23 -07:00
@@ -524,6 +524,54 @@
 };
 
 /*
+ * clock mode selection
+ */
+static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[3] = {
+		"Auto", "Internal", "External"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item > 2)
+		uinfo->value.enumerated.item = 2;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = chip->clock_mode;
+	return 0;
+}
+
+static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+	down(&chip->mixer_mutex);
+	if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
+		chip->clock_mode = ucontrol->value.enumerated.item[0];
+		vx_set_clock(chip, chip->freq);
+		up(&chip->mixer_mutex);
+		return 1;
+	}
+	up(&chip->mixer_mutex);
+	return 0;
+}
+
+static snd_kcontrol_new_t vx_control_clock_mode = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"Clock Mode",
+	.info =		vx_clock_mode_info,
+	.get =		vx_clock_mode_get,
+	.put =		vx_clock_mode_put,
+};
+
+/*
  * Audio Gain
  */
 static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -912,6 +960,9 @@
 
 	/* Audio source */
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
+		return err;
+	/* clock mode */
+	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
 		return err;
 	/* IEC958 controls */
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
diff -Nru a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
--- a/sound/drivers/vx/vx_pcm.c	2004-06-26 17:13:23 -07:00
+++ b/sound/drivers/vx/vx_pcm.c	2004-06-26 17:13:23 -07:00
@@ -48,6 +48,7 @@
 #include <sound/driver.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
@@ -381,7 +382,7 @@
  */
 static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
 {
-	int err, i, cur_state, delay;
+	int err, i, cur_state;
 
 	/* Check the pipe is not already in the requested state */
 	if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
@@ -394,17 +395,14 @@
 	 * enough sound buffer for this pipe)
 	 */
 	if (state) {
-		int delay = CAN_START_DELAY;
 		for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
-			snd_vx_delay(chip, delay);
 			err = vx_pipe_can_start(chip, pipe);
 			if (err > 0)
 				break;
 			/* Wait for a few, before asking again
 			 * to avoid flooding the DSP with our requests
 			 */
-			if ((i % 4 ) == 0)
-				delay <<= 1;
+			mdelay(1);
 		}
 	}
     
@@ -418,15 +416,12 @@
 	 * reaching the expected state before returning
 	 * Check one pipe only (since they are synchronous)
 	 */
-	delay = WAIT_STATE_DELAY;
 	for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
-		snd_vx_delay(chip, delay);
 		err = vx_get_pipe_state(chip, pipe, &cur_state);
 		if (err < 0 || cur_state == state)
 			break;
 		err = -EIO;
-		if ((i % 4 ) == 0)
-			delay <<= 1;
+		mdelay(1);
 	}
 	return err < 0 ? -EIO : 0;
 }
diff -Nru a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
--- a/sound/drivers/vx/vx_uer.c	2004-06-26 17:13:23 -07:00
+++ b/sound/drivers/vx/vx_uer.c	2004-06-26 17:13:23 -07:00
@@ -263,17 +263,17 @@
 	/* change the audio source if possible */
 	vx_sync_audio_source(chip);
 
-	switch (chip->audio_source) {
-	case VX_AUDIO_SRC_DIGITAL:
+	if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL ||
+	    (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+	     chip->audio_source == VX_AUDIO_SRC_DIGITAL)) {
 		if (chip->clock_source != UER_SYNC) {
 			vx_change_clock_source(chip, UER_SYNC);
 			mdelay(6);
 			src_changed = 1;
 		}
-		if (chip->freq == freq)
-			return 0;
-		break;
-	default:
+	} else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL ||
+		   (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+		    chip->audio_source != VX_AUDIO_SRC_DIGITAL)) {
 		if (chip->clock_source != INTERNAL_QUARTZ) {
 			vx_change_clock_source(chip, INTERNAL_QUARTZ);
 			src_changed = 1;
@@ -283,8 +283,9 @@
 		vx_set_internal_clock(chip, freq);
 		if (src_changed)
 			vx_modify_board_inputs(chip);
-		break;
 	}
+	if (chip->freq == freq)
+		return 0;
 	chip->freq = freq;
 	vx_modify_board_clock(chip, 1);
 	return 0;
diff -Nru a/sound/isa/Kconfig b/sound/isa/Kconfig
--- a/sound/isa/Kconfig	2004-06-26 17:13:23 -07:00
+++ b/sound/isa/Kconfig	2004-06-26 17:13:23 -07:00
@@ -77,11 +77,15 @@
 	help
 	  Say 'Y' or 'M' to include support for ESS AudioDrive ES18xx chips.
 
+config SND_GUS_SYNTH
+	tristate
+
 config SND_GUSCLASSIC
 	tristate "Gravis UltraSound Classic"
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound Classic soundcard.
 
@@ -91,6 +95,7 @@
 	select SND_HWDEP
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound Extreme soundcard.
 
@@ -99,6 +104,7 @@
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound MAX soundcard.
 
@@ -107,6 +113,7 @@
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
 	  (Gravis UltraSound Plug & Play, STB SoundRage32, MED3210, Dynasonic Pro,
@@ -117,6 +124,7 @@
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
 	  with TEA6330T bass and treble regulator (UltraSound 32-Pro).
diff -Nru a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile
--- a/sound/isa/gus/Makefile	2004-06-26 17:13:23 -07:00
+++ b/sound/isa/gus/Makefile	2004-06-26 17:13:23 -07:00
@@ -27,14 +27,10 @@
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-gus-synth.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o
 
 obj-m := $(sort $(obj-m))
diff -Nru a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
--- a/sound/isa/opti9xx/opti92x-ad1848.c	2004-06-26 17:13:23 -07:00
+++ b/sound/isa/opti9xx/opti92x-ad1848.c	2004-06-26 17:13:23 -07:00
@@ -474,7 +474,6 @@
 	unsigned char dma_bits;
 	unsigned char mpu_port_bits = 0;
 	unsigned char mpu_irq_bits;
-	unsigned long flags;
 
 	switch (chip->hardware) {
 #ifndef OPTi93X
@@ -601,13 +600,11 @@
 	dma_bits |= 0x04;
 #endif	/* CS4231 || OPTi93X */
 
-	spin_lock_irqsave(&chip->lock, flags);
 #ifndef OPTi93X
 	 outb(irq_bits << 3 | dma_bits, chip->wss_base);
 #else /* OPTi93X */
 	snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
 #endif /* OPTi93X */
-	spin_unlock_irqrestore(&chip->lock, flags);
 
 __skip_resources:
 	if (chip->hardware > OPTi9XX_HW_82C928) {
@@ -767,15 +764,10 @@
 
 static void snd_opti93x_mute(opti93x_t *chip, int mute)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
 	mute = mute ? 1 : 0;
-	if (chip->mute == mute) {
-		spin_unlock_irqrestore(&chip->lock, flags);
+	if (chip->mute == mute)
 		return;
-	}
+
 	chip->mute = mute;
 
 	snd_opti93x_mute_reg(chip, OPTi93X_CD_LEFT_INPUT, mute);
@@ -800,8 +792,6 @@
 	snd_opti93x_mute_reg(chip, OPTi93X_MIC_RIGHT_INPUT, mute);
 	snd_opti93x_mute_reg(chip, OPTi93X_OUT_LEFT, mute);
 	snd_opti93x_mute_reg(chip, OPTi93X_OUT_RIGHT, mute);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 
@@ -873,10 +863,8 @@
 
 static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
 {
-	unsigned long flags;
 	unsigned char mask;
 
-	spin_lock_irqsave(&chip->lock, flags);
 	snd_opti93x_mute(chip, 1);
 
 	snd_opti93x_mce_up(chip);
@@ -885,14 +873,10 @@
 	snd_opti93x_mce_down(chip);
 
 	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
 	snd_opti93x_mute(chip, 1);
 
 	snd_opti93x_mce_up(chip);
@@ -904,7 +888,6 @@
 	snd_opti93x_mce_down(chip);
 
 	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 
diff -Nru a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
--- a/sound/isa/wavefront/wavefront_synth.c	2004-06-26 17:13:23 -07:00
+++ b/sound/isa/wavefront/wavefront_synth.c	2004-06-26 17:13:23 -07:00
@@ -1961,6 +1961,12 @@
 			break;
 		}
 
+		if (section_length < 0 || section_length > WF_SECTION_MAX) {
+			snd_printk ("invalid firmware section length %d\n",
+				    section_length);
+			goto failure;
+		}
+
 		if (sys_read (fd, section, section_length) != section_length) {
 			snd_printk ("firmware section "
 				"read error.\n");
diff -Nru a/sound/parisc/harmony.c b/sound/parisc/harmony.c
--- a/sound/parisc/harmony.c	2004-06-26 17:13:23 -07:00
+++ b/sound/parisc/harmony.c	2004-06-26 17:13:23 -07:00
@@ -556,7 +556,7 @@
 	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 
 	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 
 	/* number of channels */
 	if (runtime->channels == 2)
@@ -587,7 +587,7 @@
 	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 	
 	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 	
 	/* number of channels */
 	if (runtime->channels == 1)
@@ -751,6 +751,8 @@
 	int err;
 	
 	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+	if (err > 0 && substream->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS)
+		substream->runtime->dma_addr = __pa(substream->runtime->dma_area);
 	DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,
 			(unsigned long)substream->runtime->dma_addr);
 	return err;
@@ -784,7 +786,7 @@
 	.pointer =		snd_card_harmony_capture_pointer,
 };
 
-static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
+static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony)
 {
 	snd_pcm_t *pcm;
 	int err;
@@ -797,7 +799,7 @@
 	
 	snd_harmony_disable_interrupts(harmony);
 	
-   	if ((err = snd_pcm_new(harmony->card, "Harmony", device, 1, 1, &pcm)) < 0)
+   	if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0)
 		return err;
 	
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops);
@@ -813,26 +815,46 @@
 	harmony->dma_dev.dev = &harmony->pa_dev->dev;
 	err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
 				  &harmony->graveyard_dma);
-	if (err < 0)
+	if (err == -ENOMEM) {
+		/* use continuous buffers */
+		harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+		harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL);
+		err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+					  &harmony->graveyard_dma);
+	}
+	if (err < 0) {
+		printk(KERN_ERR PFX "can't allocate graveyard buffer\n");
 		return err;
+	}
 	harmony->graveyard_count = 0;
 	
 	/* initialize silence buffers */
 	err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*SILENCE_BUFS,
 				  &harmony->silence_dma);
-	if (err < 0)
+	if (err < 0) {
+		printk(KERN_ERR PFX "can't allocate silence buffer\n");
 		return err;
+	}
 	harmony->silence_count = 0;
 
+	if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) {
+		harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area);
+		harmony->silence_dma.addr = __pa(harmony->silence_dma.area);
+	}
+
 	harmony->ply_stopped = harmony->cap_stopped = 1;
 	
 	harmony->playback_substream = NULL;
 	harmony->capture_substream = NULL;
 	harmony->graveyard_count = 0;
-	
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-					      &harmony->pa_dev->dev,
-					      MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type,
+						    harmony->dma_dev.dev,
+						    MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+	if (err < 0) {
+		printk(KERN_ERR PFX "buffer allocation error %d\n", err);
+		// return err;
+	}
 
 	return 0;
 }
@@ -1037,7 +1059,7 @@
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_card_harmony_pcm_init(chip, dev)) < 0) {
+	if ((err = snd_card_harmony_pcm_init(chip)) < 0) {
 		printk(KERN_ERR PFX "PCM Init failed\n");
 		snd_card_free(card);
 		return err;
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ac97/ac97_codec.c	2004-06-26 17:13:23 -07:00
@@ -108,12 +108,13 @@
 { 0x41445375, 0xffffffff, "AD1985",		patch_ad1985,	NULL },
 { 0x414c4300, 0xffffff00, "ALC100/100P", 	NULL,		NULL },
 { 0x414c4710, 0xfffffff0, "ALC200/200P",	NULL,		NULL },
+{ 0x414c4721, 0xffffffff, "ALC650D",		NULL,	NULL }, /* already patched */
+{ 0x414c4722, 0xffffffff, "ALC650E",		NULL,	NULL }, /* already patched */
+{ 0x414c4723, 0xffffffff, "ALC650F",		NULL,	NULL }, /* already patched */
 { 0x414c4720, 0xfffffff0, "ALC650",		patch_alc650,	NULL },
-{ 0x414c4721, 0xfffffff0, "ALC650D",		patch_alc650,	NULL },
-{ 0x414c4722, 0xfffffff0, "ALC650E",		patch_alc650,	NULL },
-{ 0x414c4723, 0xfffffff0, "ALC650F",		patch_alc650,	NULL },
 { 0x414c4760, 0xfffffff0, "ALC655",		patch_alc655,	NULL },
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
+{ 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
 { 0x414c4730, 0xffffffff, "ALC101",		NULL,		NULL },
 { 0x414c4740, 0xfffffff0, "ALC202",		NULL,		NULL },
 { 0x414c4750, 0xfffffff0, "ALC250",		NULL,		NULL },
@@ -274,7 +275,7 @@
 {
 	if (!snd_ac97_valid_reg(ac97, reg))
 		return;
-	if ((ac97->id & 0xffffff00) == 0x414c4300) {
+	if ((ac97->id & 0xffffff00) == AC97_ID_ALC100) {
 		/* Fix H/W bug of ALC100/100P */
 		if (reg == AC97_MASTER || reg == AC97_HEADPHONE)
 			ac97->bus->write(ac97, AC97_RESET, 0);	/* reset audio codec */
@@ -398,7 +399,7 @@
 	int change;
 	unsigned short old, new, cfg;
 
-	down(&ac97->spec.ad18xx.mutex);
+	down(&ac97->mutex);
 	spin_lock(&ac97->reg_lock);
 	old = ac97->spec.ad18xx.pcmreg[codec];
 	new = (old & ~mask) | value;
@@ -418,7 +419,7 @@
 				 cfg | 0x7000);
 	} else
 		spin_unlock(&ac97->reg_lock);
-	up(&ac97->spec.ad18xx.mutex);
+	up(&ac97->mutex);
 	return change;
 }
 
@@ -545,7 +546,7 @@
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
 	
 	ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask;
 	if (invert)
@@ -559,7 +560,7 @@
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
 	unsigned short val;
 	
 	val = (ucontrol->value.integer.value[0] & mask);
@@ -625,6 +626,40 @@
 				    (val1 << shift_left) | (val2 << shift_right));
 }
 
+int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol,
+			 int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *))
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int err;
+
+	if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
+	    (reg >= 0x60 && reg < 0x70)) {
+		unsigned short page_save;
+		unsigned short page = (kcontrol->private_value >> 25) & 0x0f;
+		down(&ac97->mutex); /* lock paging */
+		page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+		err = func(kcontrol, ucontrol);
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+		up(&ac97->mutex); /* unlock paging */
+	} else
+		err = func(kcontrol, ucontrol);
+	return err;
+}
+
+/* for rev2.3 paging */
+int snd_ac97_page_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_single);
+}
+
+/* for rev2.3 paging */
+int snd_ac97_page_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_single);
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
 AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
 AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
@@ -1120,6 +1155,7 @@
 	snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check the volume resolution of center/lfe */
 static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max)
 {
 	unsigned short val, val1;
@@ -1135,6 +1171,7 @@
 	snd_ac97_write_cache(ac97, reg, 0x8080);
 }
 
+/* check whether the volume resolution is 4 or 5 bits */
 static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char *max)
 {
 	unsigned short val, val1;
@@ -1150,6 +1187,18 @@
 	snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check whether the volume is mono or stereo */
+static int snd_ac97_is_stereo_vol(ac97_t *ac97, int reg)
+{
+	unsigned short val, val1, val2;
+	val = snd_ac97_read(ac97, reg);
+	val1 = val | 0x8000 | (0x01 << 8);
+	snd_ac97_write(ac97, reg, val1);
+	val2 = snd_ac97_read(ac97, reg);
+	snd_ac97_write(ac97, reg, val); /* restore */
+	return val1 == val2;
+}
+
 static inline int printable(unsigned int x)
 {
 	x &= 0xff;
@@ -1239,6 +1288,8 @@
 }
 
 
+static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97);
+
 static int snd_ac97_mixer_build(ac97_t * ac97)
 {
 	snd_card_t *card = ac97->bus->card;
@@ -1293,11 +1344,8 @@
 	}
 
 	/* build headphone controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) {
-		const char *name = ac97->id == AC97_ID_STAC9708 ? 
-			"Sigmatel Surround Playback" :
-			"Headphone Playback";
-		if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0)
+	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {
+		if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, 1, ac97)) < 0)
 			return err;
 	}
 	
@@ -1332,7 +1380,8 @@
 		for (idx = 0; idx < 2; idx++)
 			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 				return err;
-		snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+		snd_ac97_write_cache(ac97, AC97_PC_BEEP,
+				     snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);
 	}
 	
 	/* build Phone controls */
@@ -1349,15 +1398,26 @@
 	
 	/* build MIC controls */
 	snd_ac97_change_volume_params3(ac97, AC97_MIC, &max);
-	for (idx = 0; idx < 3; idx++) {
-		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+	if (snd_ac97_is_stereo_vol(ac97, AC97_MIC)) {
+		/* build stereo mic */
+		if ((err = snd_ac97_cmute_new(card, "Mic Playback Switch", AC97_MIC, ac97)) < 0)
 			return err;
-		if (idx == 1) {		// volume
-			kctl->private_value &= ~(0xff << 16);
-			kctl->private_value |= (int)max << 16;
+		if ((err = snd_ac97_cvol_new(card, "Mic Playback Volume", AC97_MIC, max, ac97)) < 0)
+			return err;
+		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[2], ac97))) < 0)
+			return err;
+	} else {
+		/* build mono mic */
+		for (idx = 0; idx < 3; idx++) {
+			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+				return err;
+			if (idx == 1) {		// volume
+				kctl->private_value &= ~(0xff << 16);
+				kctl->private_value |= (int)max << 16;
+			}
 		}
+		snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 	}
-	snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 
 	/* build Line controls */
 	if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0)
@@ -1410,9 +1470,7 @@
 		if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0)
 			return err;
 		/* FIXME: C-Media chips have no PCM volume!! */
-		if (/*ac97->id == 0x434d4941 ||*/
-		    ac97->id == 0x434d4942 ||
-		    ac97->id == 0x434d4961)
+		if (ac97->id == AC97_ID_CM9739)
 			snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
 		else {
 			if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0)
@@ -1520,6 +1578,7 @@
 			/* set default PCM S/PDIF params */
 			/* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
 			snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
+			ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
 		}
 		ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
 	}
@@ -1675,7 +1734,7 @@
 		if (snd_ac97_read(ac97, AC97_REC_GAIN) == 0x8a05)
 			return 0;
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100);
+		schedule_timeout(1);
 	} while (time_after_eq(end_time, jiffies));
 	return -ENODEV;
 }
@@ -1774,6 +1833,7 @@
 	ac97->bus = bus;
 	bus->codec[ac97->num] = ac97;
 	spin_lock_init(&ac97->reg_lock);
+	init_MUTEX(&ac97->mutex);
 
 	if (ac97->pci) {
 		pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
@@ -1789,8 +1849,14 @@
 		bus->wait(ac97);
 	else {
 		udelay(50);
-		if (ac97_reset_wait(ac97, HZ/2, 0) < 0 &&
-		    ac97_reset_wait(ac97, HZ/2, 1) < 0) {
+		if (ac97->scaps & AC97_SCAP_SKIP_AUDIO)
+			err = ac97_reset_wait(ac97, HZ/2, 1);
+		else {
+			err = ac97_reset_wait(ac97, HZ/2, 0);
+			if (err < 0)
+				err = ac97_reset_wait(ac97, 0, 1);
+		}
+		if (err < 0) {
 			snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num);
 			/* proceed anyway - it's often non-critical */
 		}
@@ -1803,20 +1869,6 @@
 		snd_ac97_free(ac97);
 		return -EIO;
 	}
-	/* AC97 audio codec chip revision detection. */
-	/* Currently only Realtek ALC650 detection implemented. */
-	switch(ac97->id & 0xfffffff0) {
-	case 0x414c4720:        /* ALC650 */
-		reg = snd_ac97_read(ac97, AC97_ALC650_REVISION);
-		if (((reg & 0x3f) >= 0) && ((reg & 0x3f) < 3))
-			ac97->id = 0x414c4720;          /* Old version */
-		else if (((reg & 0x3f) >= 3) && ((reg & 0x3f) < 0x10))
-			ac97->id = 0x414c4721;          /* D version */
-		else if ((reg&0x30) == 0x10)
-			ac97->id = 0x414c4722;          /* E version */
-		else if ((reg&0x30) == 0x20)
-			ac97->id = 0x414c4723;          /* F version */
-        }
 	
 	/* test for AC'97 */
 	if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
@@ -1865,9 +1917,9 @@
 			if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
 				goto __ready_ok;
 			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/10);
+			schedule_timeout(1);
 		} while (time_after_eq(end_time, jiffies));
-		snd_printk(KERN_ERR "AC'97 %d analog subsections not ready\n", ac97->num);
+		snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num);
 	}
 
 	/* FIXME: add powerdown control */
@@ -1898,9 +1950,9 @@
 			if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
 				goto __ready_ok;
 			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/10);
+			schedule_timeout(1);
 		} while (time_after_eq(end_time, jiffies));
-		snd_printk(KERN_ERR "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
+		snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
 	}
 	
       __ready_ok:
@@ -1919,12 +1971,7 @@
 	}
 	if (ac97->ext_id & AC97_EI_SPDIF) {
 		/* codec specific code (patch) should override these values */
-		if (ac97->flags & AC97_CS_SPDIF)
-			ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100;
-		else if (ac97->id == AC97_ID_CM9739)
-			ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
-		else
-			ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000;
 	}
 	if (ac97->ext_id & AC97_EI_VRM) {	/* MIC VRA support */
 		snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]);
@@ -1942,8 +1989,8 @@
 	/* additional initializations */
 	if (bus->init)
 		bus->init(ac97);
-	snd_ac97_get_name(ac97, ac97->id, name, 0);
-	snd_ac97_get_name(NULL, ac97->id, name, 0);  // ac97->id might be changed in the special setup code
+	snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
+	snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97));  // ac97->id might be changed in the special setup code
 	if (ac97_is_audio(ac97)) {
 		if (card->mixername[0] == '\0') {
 			strcpy(card->mixername, name);
@@ -2066,18 +2113,28 @@
 	snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
-	ac97->bus->write(ac97, AC97_MASTER, 0x8101);
-	for (i = 0; i < 10; i++) {
-		if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-	}
-	/* FIXME: extra delay */
-	ac97->bus->write(ac97, AC97_MASTER, 0x8000);
-	if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/4);
+	if (ac97_is_audio(ac97)) {
+		ac97->bus->write(ac97, AC97_MASTER, 0x8101);
+		for (i = HZ/10; i >= 0; i--) {
+			if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
+				break;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		}
+		/* FIXME: extra delay */
+		ac97->bus->write(ac97, AC97_MASTER, 0x8000);
+		if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ/4);
+		}
+	} else {
+		for (i = HZ/10; i >= 0; i--) {
+			unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+			if (val != 0xffff && (val & 1) != 0)
+				break;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		}
 	}
 __reset_ready:
 
@@ -2151,42 +2208,57 @@
 
 /*
  */
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name)
+static void set_ctl_name(char *dst, const char *src, const char *suffix)
+{
+	if (suffix)
+		sprintf(dst, "%s %s", src, suffix);
+	else
+		strcpy(dst, src);
+}	
+
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix)
 {
 	snd_ctl_elem_id_t id;
 	memset(&id, 0, sizeof(id));
-	strcpy(id.name, name);
+	set_ctl_name(id.name, name, suffix);
 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	return snd_ctl_remove_id(ac97->bus->card, &id);
 }
 
-static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name)
+static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suffix)
 {
 	snd_ctl_elem_id_t sid;
 	memset(&sid, 0, sizeof(sid));
-	strcpy(sid.name, name);
+	set_ctl_name(sid.name, name, suffix);
 	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	return snd_ctl_find_id(ac97->bus->card, &sid);
 }
 
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst)
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix)
 {
-	snd_kcontrol_t *kctl = ctl_find(ac97, src);
+	snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix);
 	if (kctl) {
-		strcpy(kctl->id.name, dst);
+		set_ctl_name(kctl->id.name, dst, suffix);
 		return 0;
 	}
 	return -ENOENT;
 }
 
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2)
+/* rename both Volume and Switch controls - don't check the return value */
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst)
+{
+	snd_ac97_rename_ctl(ac97, src, dst, "Switch");
+	snd_ac97_rename_ctl(ac97, src, dst, "Volume");
+}
+
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix)
 {
 	snd_kcontrol_t *kctl1, *kctl2;
-	kctl1 = ctl_find(ac97, s1);
-	kctl2 = ctl_find(ac97, s2);
+	kctl1 = ctl_find(ac97, s1, suffix);
+	kctl2 = ctl_find(ac97, s2, suffix);
 	if (kctl1 && kctl2) {
-		strcpy(kctl1->id.name, s2);
-		strcpy(kctl2->id.name, s1);
+		set_ctl_name(kctl1->id.name, s2, suffix);
+		set_ctl_name(kctl2->id.name, s1, suffix);
 		return 0;
 	}
 	return -ENOENT;
@@ -2194,26 +2266,22 @@
 
 static int swap_headphone(ac97_t *ac97, int remove_master)
 {
-	/* FIXME: error checks.. */
 	if (remove_master) {
-		if (ctl_find(ac97, "Headphone Playback Switch") == NULL)
+		if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
 			return 0;
-		snd_ac97_remove_ctl(ac97, "Master Playback Switch");
-		snd_ac97_remove_ctl(ac97, "Master Playback Volume");
-	} else {
-		snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback Switch");
-		snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback Volume");
-	}
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+		snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
+		snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
+	} else
+		snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return 0;
 }
 
 static int swap_surround(ac97_t *ac97)
 {
 	/* FIXME: error checks.. */
-	snd_ac97_swap_ctl(ac97, "Master Playback Switch", "Surround Playback Switch");
-	snd_ac97_swap_ctl(ac97, "Master Playback Volume", "Surround Playback Volume");
+	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch");
+	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume");
 	return 0;
 }
 
diff -Nru a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
--- a/sound/pci/ac97/ac97_id.h	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ac97/ac97_id.h	2004-06-26 17:13:23 -07:00
@@ -45,7 +45,14 @@
 #define AC97_ID_CS4201		0x43525948
 #define AC97_ID_CS4205		0x43525958
 #define AC97_ID_CS_MASK		0xfffffff8	/* bit 0-2: rev */
+#define AC97_ID_ALC100		0x414c4300
 #define AC97_ID_ALC650		0x414c4720
+#define AC97_ID_ALC650D		0x414c4721
+#define AC97_ID_ALC650E		0x414c4722
+#define AC97_ID_ALC650F		0x414c4723
+#define AC97_ID_ALC655		0x414c4760
+#define AC97_ID_ALC658		0x414c4780
+#define AC97_ID_ALC850		0x414c4790
 #define AC97_ID_YMF753		0x594d4803
 #define AC97_ID_VT1616		0x49434551
 #define AC97_ID_CM9738		0x434d4941
diff -Nru a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
--- a/sound/pci/ac97/ac97_local.h	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ac97/ac97_local.h	2004-06-26 17:13:23 -07:00
@@ -23,10 +23,15 @@
  */
 
 #define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24))
+#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) | ((page) << 25))
 #define AC97_SINGLE(xname, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
   .get = snd_ac97_get_single, .put = snd_ac97_put_single, \
   .private_value =  AC97_SINGLE_VALUE(reg, shift, mask, invert) }
+#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page)		\
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
+  .get = snd_ac97_page_get_single, .put = snd_ac97_page_put_single, \
+  .private_value =  AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
 
 /* ac97_codec.c */
 extern const char *snd_ac97_stereo_enhancements[];
@@ -37,10 +42,13 @@
 int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_page_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_page_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name);
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst);
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2);
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix);
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix);
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix);
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
 
 /* ac97_proc.c */
 void snd_ac97_bus_proc_init(ac97_bus_t * ac97);
diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
--- a/sound/pci/ac97/ac97_patch.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ac97/ac97_patch.c	2004-06-26 17:13:23 -07:00
@@ -51,6 +51,21 @@
 	return 0;
 }
 
+/* set to the page, update bits and restore the page */
+static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
+{
+	unsigned short page_save;
+	int ret;
+
+	down(&ac97->mutex);
+	page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+	ret = snd_ac97_update_bits(ac97, reg, mask, value);
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+	up(&ac97->mutex); /* unlock paging */
+	return ret;
+}
+
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 
 /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -204,7 +219,7 @@
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control - Wide");
-	kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
 		return err;
@@ -315,7 +330,7 @@
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-	kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	return 0;
 }
@@ -328,11 +343,11 @@
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-	kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
-	kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	return 0;
 }
@@ -373,17 +388,23 @@
 	.build_specific	= patch_sigmatel_stac97xx_specific
 };
 
-static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
-	.build_3d	= patch_sigmatel_stac9708_3d,
-	.build_specific	= patch_sigmatel_stac97xx_specific
-};
-
 int patch_sigmatel_stac9700(ac97_t * ac97)
 {
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
 	return 0;
 }
 
+static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
+{
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
+	return patch_sigmatel_stac97xx_specific(ac97);
+}
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
+	.build_3d	= patch_sigmatel_stac9708_3d,
+	.build_specific	= patch_sigmatel_stac9708_specific
+};
+
 int patch_sigmatel_stac9708(ac97_t * ac97)
 {
 	unsigned int codec72, codec6c;
@@ -467,11 +488,11 @@
 	int shift = kcontrol->private_value;
 	unsigned short val;
 
-	val = ac97->regs[AC97_SIGMATEL_OUTSEL];
-	if (!((val >> shift) & 4))
+	val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
+	if (!(val & 4))
 		ucontrol->value.enumerated.item[0] = 0;
 	else
-		ucontrol->value.enumerated.item[0] = 1 + ((val >> shift) & 3);
+		ucontrol->value.enumerated.item[0] = 1 + (val & 3);
 	return 0;
 }
 
@@ -480,6 +501,7 @@
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	int shift = kcontrol->private_value;
 	unsigned short val;
+	int ret;
 
 	if (ucontrol->value.enumerated.item[0] > 4)
 		return -EINVAL;
@@ -487,8 +509,10 @@
 		val = 0;
 	else
 		val = 4 | (ucontrol->value.enumerated.item[0] - 1);
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL,
-				    7 << shift, val << shift);
+	ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL,
+				   7 << shift, val << shift);
+	up(&ac97->mutex);
+	return ret;
 }
 
 static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -521,8 +545,8 @@
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	int shift = kcontrol->private_value;
 
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
-				    ucontrol->value.enumerated.item[0] << shift);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
+				     ucontrol->value.enumerated.item[0] << shift, 0);
 }
 
 static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -550,8 +574,8 @@
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3,
-				    ucontrol->value.enumerated.item[0]);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
+				     ucontrol->value.enumerated.item[0], 0);
 }
 
 #define STAC9758_OUTPUT_JACK(xname, shift) \
@@ -596,6 +620,14 @@
 				   ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
 	if (err < 0)
 		return err;
+	/* DAC-A direct */
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
+	/* DAC-A to Mix = PCM */
+	/* DAC-B direct = Surround */
+	/* DAC-B to Mix */
+	snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
+	/* DAC-C direct = Center/LFE */
+
 	return 0;
 }
 
@@ -613,16 +645,16 @@
 		AC97_SIGMATEL_VARIOUS
 	};
 	static unsigned short def_regs[4] = {
-		/* OUTSEL */ 0xd794,
+		/* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
 		/* IOMISC */ 0x2001,
-		/* INSEL */ 0x0201,
+		/* INSEL */ 0x0201, /* LI:LI, MI:M1 */
 		/* VARIOUS */ 0x0040
 	};
 	static unsigned short m675_regs[4] = {
-		/* OUTSEL */ 0x9040,
-		/* IOMISC */ 0x2102,
-		/* INSEL */ 0x0203,
-		/* VARIOUS */ 0x0041
+		/* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
+		/* IOMISC */ 0x2102, /* HP amp on */
+		/* INSEL */ 0x0203, /* LI:LI, MI:FR */
+		/* VARIOUS */ 0x0041 /* stereo mic */
 	};
 	unsigned short *pregs = def_regs;
 	int i;
@@ -635,6 +667,8 @@
 
 	// patch for SigmaTel
 	ac97->build_ops = &patch_sigmatel_stac9758_ops;
+	/* FIXME: assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
 	for (i = 0; i < 4; i++)
 		snd_ac97_write_cache(ac97, regs[i], pregs[i]);
 
@@ -654,8 +688,10 @@
 {
 	int err;
 
+	/* con mask, pro mask, default */
 	if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
 		return err;
+	/* switch, spsa */
 	if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
 		return err;
 	switch (ac97->id & AC97_ID_CS_MASK) {
@@ -714,8 +750,10 @@
 {
 	int err;
 
+	/* con mask, pro mask, default */
 	if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
 		return err;
+	/* switch */
 	if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
 		return err;
 	/* set default PCM S/PDIF params */
@@ -734,6 +772,7 @@
 	ac97->build_ops = &patch_conexant_ops;
 	ac97->flags |= AC97_CX_SPDIF;
         ac97->ext_id |= AC97_EI_SPDIF;	/* force the detection of spdif */
+	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 	return 0;
 }
 
@@ -821,8 +860,6 @@
 	unsigned short val;
 	int idx, num;
 
-	init_MUTEX(&ac97->spec.ad18xx.mutex);
-
 	val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
 	snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
 	codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
@@ -1114,10 +1151,8 @@
 static int patch_ad1888_specific(ac97_t *ac97)
 {
 	/* rename 0x04 as "Master" and 0x02 as "Master Surround" */
-	snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Master Surround Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Master Surround Playback Volume");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+	snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
 }
 
@@ -1213,7 +1248,7 @@
 }
 
 /*
- * realtek ALC65x codecs
+ * realtek ALC65x/850 codecs
  */
 static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -1303,6 +1338,17 @@
 
 	ac97->build_ops = &patch_alc650_ops;
 
+	/* determine the revision */
+	val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
+	if (val < 3)
+		ac97->id = 0x414c4720;          /* Old version */
+	else if (val < 0x10)
+		ac97->id = 0x414c4721;          /* D version */
+	else if (val < 0x20)
+		ac97->id = 0x414c4722;          /* E version */
+	else if (val < 0x30)
+		ac97->id = 0x414c4723;          /* F version */
+
 	/* revision E or F */
 	/* FIXME: what about revision D ? */
 	ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
@@ -1351,20 +1397,19 @@
 static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        int change;
 
 	/* misc control; vrefout disable */
 	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
 			     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-	change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-				      ucontrol->value.integer.value[0] ? (1 << 10) : 0);
-	return change;
+	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+				     ucontrol->value.integer.value[0] ? (1 << 10) : 0,
+				     0);
 }
 
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
-	AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
-	AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+	AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Mic As Center/LFE",
@@ -1391,7 +1436,6 @@
 	       texts_658[uinfo->value.enumerated.item] :
 	       texts_655[uinfo->value.enumerated.item]);
 	return 0;
-
 }
 
 static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
@@ -1410,13 +1454,15 @@
 static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	return snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 3 << 12,
-				    (unsigned short)ucontrol->value.enumerated.item[0]);
+
+	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
+				     (unsigned short)ucontrol->value.enumerated.item[0],
+				     0);
 }
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = {
-        AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
-        AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0),
+        AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0),
+        AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0),
 	{
 		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name   = "IEC958 Playback Route",
@@ -1451,6 +1497,9 @@
 
 	ac97->build_ops = &patch_alc655_ops;
 
+	/* assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+
 	/* adjust default values */
 	val = snd_ac97_read(ac97, 0x7a); /* misc control */
 	val |= (1 << 1); /* spdif input pin */
@@ -1469,6 +1518,120 @@
 	return 0;
 }
 
+
+#define AC97_ALC850_JACK_SELECT	0x76
+#define AC97_ALC850_MISC1	0x7a
+
+static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
+        return 0;
+}
+
+static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	/* SURR 1kOhm (bit4), Amp (bit5) */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
+			     ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
+	/* LINE-IN = 0, SURROUND = 2 */
+	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+				    ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
+}
+
+static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
+        return 0;
+}
+
+static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	/* Vref disable (bit12), 1kOhm (bit13) */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
+			     ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
+	/* MIC-IN = 1, CENTER-LFE = 2 */
+	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+				    ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
+}
+
+static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
+	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line-In As Surround",
+		.info = snd_ac97_info_single,
+		.get = ac97_alc850_surround_get,
+		.put = ac97_alc850_surround_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Mic As Center/LFE",
+		.info = snd_ac97_info_single,
+		.get = ac97_alc850_mic_get,
+		.put = ac97_alc850_mic_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+
+};
+
+static int patch_alc850_specific(ac97_t *ac97)
+{
+	int err;
+
+	if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
+		return err;
+	if (ac97->ext_id & AC97_EI_SPDIF) {
+		if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+static struct snd_ac97_build_ops patch_alc850_ops = {
+	.build_specific	= patch_alc850_specific
+};
+
+int patch_alc850(ac97_t *ac97)
+{
+	ac97->build_ops = &patch_alc850_ops;
+
+	ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
+
+	/* assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+
+	/* adjust default values */
+	/* set default: spdif-in enabled,
+	   spdif-in monitor off, spdif-in PCM off
+	   center on mic off, surround on line-in off
+	   duplicate front off
+	*/
+	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
+	/* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
+	 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
+	 */
+	snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
+			     (1<<7)|(0<<12)|(1<<13)|(0<<14));
+	/* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
+	 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
+	 */
+	snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
+			     (1<<11)|(0<<12)|(1<<15));
+
+	/* full DAC volume */
+	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
+	snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+	return 0;
+}
+
+
 /*
  * C-Media CM97xx codecs
  */
@@ -1599,8 +1762,10 @@
 		/* enable spdif in */
 		snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
 				     snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 	} else {
 		ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
+		ac97->rates[AC97_RATES_SPDIF] = 0;
 	}
 
 	/* set-up multi channel */
diff -Nru a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
--- a/sound/pci/ac97/ac97_patch.h	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ac97/ac97_patch.h	2004-06-26 17:13:23 -07:00
@@ -49,6 +49,7 @@
 int patch_ad1985(ac97_t * ac97);
 int patch_alc650(ac97_t * ac97);
 int patch_alc655(ac97_t * ac97);
+int patch_alc850(ac97_t * ac97);
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
diff -Nru a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
--- a/sound/pci/ac97/ac97_proc.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ac97/ac97_proc.c	2004-06-26 17:13:23 -07:00
@@ -292,9 +292,9 @@
 {
 	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
 	
+	down(&ac97->mutex);
 	if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {	// Analog Devices AD1881/85/86
 		int idx;
-		down(&ac97->spec.ad18xx.mutex);
 		for (idx = 0; idx < 3; idx++)
 			if (ac97->spec.ad18xx.id[idx]) {
 				/* select single codec */
@@ -305,7 +305,6 @@
 			}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-		up(&ac97->spec.ad18xx.mutex);
 		
 		snd_iprintf(buffer, "\nAD18XX configuration\n");
 		snd_iprintf(buffer, "Unchained        : 0x%04x,0x%04x,0x%04x\n",
@@ -319,6 +318,7 @@
 	} else {
 		snd_ac97_proc_read_main(ac97, buffer, 0);
 	}
+	up(&ac97->mutex);
 }
 
 #ifdef CONFIG_SND_DEBUG
@@ -328,6 +328,7 @@
 	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
 	char line[64];
 	unsigned int reg, val;
+	down(&ac97->mutex);
 	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 		if (sscanf(line, "%x %x", &reg, &val) != 2)
 			continue;
@@ -335,6 +336,7 @@
 		if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
 			snd_ac97_write_cache(ac97, reg, val);
 	}
+	up(&ac97->mutex);
 }
 #endif
 
@@ -353,10 +355,10 @@
 {
 	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
 
+	down(&ac97->mutex);
 	if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {	// Analog Devices AD1881/85/86
 
 		int idx;
-		down(&ac97->spec.ad18xx.mutex);
 		for (idx = 0; idx < 3; idx++)
 			if (ac97->spec.ad18xx.id[idx]) {
 				/* select single codec */
@@ -366,10 +368,10 @@
 			}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-		up(&ac97->spec.ad18xx.mutex);
 	} else {
 		snd_ac97_proc_regs_read_main(ac97, buffer, 0);
 	}	
+	up(&ac97->mutex);
 }
 
 void snd_ac97_proc_init(ac97_t * ac97)
diff -Nru a/sound/pci/atiixp.c b/sound/pci/atiixp.c
--- a/sound/pci/atiixp.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/atiixp.c	2004-06-26 17:13:23 -07:00
@@ -1,5 +1,5 @@
 /*
- *   ALSA driver for ATI IXP 150/200/250 AC97 controllers
+ *   ALSA driver for ATI IXP 150/200/250/300 AC97 controllers
  *
  *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
  *
@@ -996,6 +996,7 @@
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_RESUME |
 				 SNDRV_PCM_INFO_MMAP_VALID),
 	.formats =		SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
@@ -1387,17 +1388,9 @@
 		ac97.num = i;
 		ac97.scaps = AC97_SCAP_SKIP_MODEM;
 		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
-			if (chip->codec_not_ready_bits)
-				/* codec(s) was detected but not available.
-				 * return the error
-				 */
-				return err;
-			else {
-				/* codec(s) was NOT detected, so just ignore here */
-				chip->ac97[i] = NULL; /* to be sure */
-				snd_printd("atiixp: codec %d not found\n", i);
-				continue;
-			}
+			chip->ac97[i] = NULL; /* to be sure */
+			snd_printdd("atiixp: codec %d not available for audio\n", i);
+			continue;
 		}
 		codec_count++;
 	}
diff -Nru a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
--- a/sound/pci/au88x0/au88x0_a3d.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/au88x0/au88x0_a3d.c	2004-06-26 17:13:23 -07:00
@@ -864,7 +864,7 @@
 		if ((kcontrol =
 		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
 			return -ENOMEM;
-		kcontrol->private_value = (int)&(vortex->a3d[i]);
+		kcontrol->private_value = (long)&(vortex->a3d[i]);
 		kcontrol->id.numid = CTRLID_HRTF;
 		kcontrol->info = snd_vortex_a3d_hrtf_info;
 		kcontrol->put = snd_vortex_a3d_hrtf_put;
@@ -876,7 +876,7 @@
 		if ((kcontrol =
 		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
 			return -ENOMEM;
-		kcontrol->private_value = (int)&(vortex->a3d[i]);
+		kcontrol->private_value = (long)&(vortex->a3d[i]);
 		kcontrol->id.numid = CTRLID_ITD;
 		kcontrol->info = snd_vortex_a3d_itd_info;
 		kcontrol->put = snd_vortex_a3d_itd_put;
@@ -888,7 +888,7 @@
 		if ((kcontrol =
 		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
 			return -ENOMEM;
-		kcontrol->private_value = (int)&(vortex->a3d[i]);
+		kcontrol->private_value = (long)&(vortex->a3d[i]);
 		kcontrol->id.numid = CTRLID_GAINS;
 		kcontrol->info = snd_vortex_a3d_ild_info;
 		kcontrol->put = snd_vortex_a3d_ild_put;
@@ -900,7 +900,7 @@
 		if ((kcontrol =
 		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
 			return -ENOMEM;
-		kcontrol->private_value = (int)&(vortex->a3d[i]);
+		kcontrol->private_value = (long)&(vortex->a3d[i]);
 		kcontrol->id.numid = CTRLID_FILTER;
 		kcontrol->info = snd_vortex_a3d_filter_info;
 		kcontrol->put = snd_vortex_a3d_filter_put;
diff -Nru a/sound/pci/cmipci.c b/sound/pci/cmipci.c
--- a/sound/pci/cmipci.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/cmipci.c	2004-06-26 17:13:23 -07:00
@@ -1072,30 +1072,36 @@
  */
 
 /* save mixer setting and mute for AC3 playback */
-static void save_mixer_state(cmipci_t *cm)
+static int save_mixer_state(cmipci_t *cm)
 {
 	if (! cm->mixer_insensitive) {
+		snd_ctl_elem_value_t *val;
 		unsigned int i;
+
+		val = kmalloc(sizeof(*val), GFP_ATOMIC);
+		if (!val)
+			return -ENOMEM;
 		for (i = 0; i < CM_SAVED_MIXERS; i++) {
 			snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
 			if (ctl) {
-				snd_ctl_elem_value_t val;
 				int event;
-				memset(&val, 0, sizeof(val));
-				ctl->get(ctl, &val);
-				cm->mixer_res_status[i] = val.value.integer.value[0];
-				val.value.integer.value[0] = cm_saved_mixer[i].toggle_on;
+				memset(val, 0, sizeof(*val));
+				ctl->get(ctl, val);
+				cm->mixer_res_status[i] = val->value.integer.value[0];
+				val->value.integer.value[0] = cm_saved_mixer[i].toggle_on;
 				event = SNDRV_CTL_EVENT_MASK_INFO;
-				if (cm->mixer_res_status[i] != val.value.integer.value[0]) {
-					ctl->put(ctl, &val); /* toggle */
+				if (cm->mixer_res_status[i] != val->value.integer.value[0]) {
+					ctl->put(ctl, val); /* toggle */
 					event |= SNDRV_CTL_EVENT_MASK_VALUE;
 				}
 				ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 				snd_ctl_notify(cm->card, event, &ctl->id);
 			}
 		}
+		kfree(val);
 		cm->mixer_insensitive = 1;
 	}
+	return 0;
 }
 
 
@@ -1103,27 +1109,32 @@
 static void restore_mixer_state(cmipci_t *cm)
 {
 	if (cm->mixer_insensitive) {
+		snd_ctl_elem_value_t *val;
 		unsigned int i;
+
+		val = kmalloc(sizeof(*val), GFP_KERNEL);
+		if (!val)
+			return;
 		cm->mixer_insensitive = 0; /* at first clear this;
 					      otherwise the changes will be ignored */
 		for (i = 0; i < CM_SAVED_MIXERS; i++) {
 			snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
 			if (ctl) {
-				snd_ctl_elem_value_t val;
 				int event;
 
-				memset(&val, 0, sizeof(val));
+				memset(val, 0, sizeof(*val));
 				ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-				ctl->get(ctl, &val);
+				ctl->get(ctl, val);
 				event = SNDRV_CTL_EVENT_MASK_INFO;
-				if (val.value.integer.value[0] != cm->mixer_res_status[i]) {
-					val.value.integer.value[0] = cm->mixer_res_status[i];
-					ctl->put(ctl, &val);
+				if (val->value.integer.value[0] != cm->mixer_res_status[i]) {
+					val->value.integer.value[0] = cm->mixer_res_status[i];
+					ctl->put(ctl, val);
 					event |= SNDRV_CTL_EVENT_MASK_VALUE;
 				}
 				snd_ctl_notify(cm->card, event, &ctl->id);
 			}
 		}
+		kfree(val);
 	}
 }
 
@@ -1175,15 +1186,16 @@
 	}
 }
 
-static void setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
+static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
 {
-	int rate;
+	int rate, err;
 	unsigned long flags;
 
 	rate = subs->runtime->rate;
 
 	if (up && do_ac3)
-		save_mixer_state(cm);
+		if ((err = save_mixer_state(cm)) < 0)
+			return err;
 
 	spin_lock_irqsave(&cm->reg_lock, flags);
 	cm->spdif_playback_avail = up;
@@ -1208,6 +1220,7 @@
 		setup_ac3(cm, subs, 0, 0);
 	}
 	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	return 0;
 }
 
 
@@ -1220,13 +1233,15 @@
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
 	int rate = substream->runtime->rate;
-	int do_spdif, do_ac3 = 0;
+	int err, do_spdif, do_ac3 = 0;
+
 	do_spdif = ((rate == 44100 || rate == 48000) &&
 		    substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE &&
 		    substream->runtime->channels == 2);
 	if (do_spdif && cm->can_ac3_hw) 
 		do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO;
-	setup_spdif_playback(cm, substream, do_spdif, do_ac3);
+	if ((err = setup_spdif_playback(cm, substream, do_spdif, do_ac3)) < 0)
+		return err;
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
 }
 
@@ -1234,12 +1249,14 @@
 static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
-	int do_ac3;
+	int err, do_ac3;
+
 	if (cm->can_ac3_hw) 
 		do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO;
 	else
 		do_ac3 = 1; /* doesn't matter */
-	setup_spdif_playback(cm, substream, 1, do_ac3);
+	if ((err = setup_spdif_playback(cm, substream, 1, do_ac3)) < 0)
+		return err;
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
 }
 
diff -Nru a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
--- a/sound/pci/cs46xx/dsp_spos.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/cs46xx/dsp_spos.c	2004-06-26 17:13:23 -07:00
@@ -1057,7 +1057,7 @@
 	
 	int fifo_addr,fifo_span,valid_slots;
 
-	spos_control_block_t sposcb = {
+	static spos_control_block_t sposcb = {
 		/* 0 */ HFG_TREE_SCB,HFG_STACK,
 		/* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
 		/* 2 */ DSP_SPOS_DC,0,
@@ -1110,18 +1110,18 @@
   
 	{
 		/* create the null SCB */
-		generic_scb_t null_scb = {
+		static generic_scb_t null_scb = {
 			{ 0, 0, 0, 0 },
 			{ 0, 0, 0, 0, 0 },
 			NULL_SCB_ADDR, NULL_SCB_ADDR,
-			null_algorithm->address, 0,
-			0,0,0,
+			0, 0, 0, 0, 0,
 			{
 				0,0,
 				0,0,
 			}
 		};
 
+		null_scb.entry_point = null_algorithm->address;
 		ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR);
 		ins->the_null_scb->task_entry = null_algorithm;
 		ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
@@ -1132,7 +1132,7 @@
 
 	{
 		/* setup foreground task tree */
-		task_tree_control_block_t fg_task_tree_hdr =  {
+		static task_tree_control_block_t fg_task_tree_hdr =  {
 			{ FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
 			  DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
@@ -1145,7 +1145,7 @@
     
 			{
 				BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 
-				fg_task_tree_header_code->address,
+				0,
 				FG_TASK_HEADER_ADDR + TCBData,                  
 			},
 
@@ -1158,7 +1158,7 @@
 			},
 
 			{
-				DSP_SPOS_DC,task_tree_thread->address,
+				DSP_SPOS_DC,0,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1200,13 +1200,15 @@
 			}
 		};
 
+		fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address;
+		fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
 		cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
 	}
 
 
 	{
 		/* setup foreground task tree */
-		task_tree_control_block_t bg_task_tree_hdr =  {
+		static task_tree_control_block_t bg_task_tree_hdr =  {
 			{ DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
@@ -1219,7 +1221,7 @@
     
 			{
 				NULL_SCB_ADDR,NULL_SCB_ADDR,  /* Set up the background to do nothing */
-				task_tree_header_code->address,
+				0,
 				BG_TREE_SCB_ADDR + TCBData,
 			},
 
@@ -1232,7 +1234,7 @@
 			},
 
 			{
-				DSP_SPOS_DC,task_tree_thread->address,
+				DSP_SPOS_DC,0,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1273,6 +1275,9 @@
 				0,0
 			}
 		};
+
+		bg_task_tree_hdr.links.entry_point = task_tree_header_code->address;
+		bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
 		cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
 	}
 
@@ -1312,7 +1317,7 @@
 	if (!write_back_scb) goto _fail_end;
 
 	{
-		mix2_ostream_spb_t mix2_ostream_spb = {
+		static mix2_ostream_spb_t mix2_ostream_spb = {
 			0x00020000,
 			0x0000ffff
 		};
diff -Nru a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
--- a/sound/pci/emu10k1/emu10k1.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/emu10k1/emu10k1.c	2004-06-26 17:13:23 -07:00
@@ -134,10 +134,6 @@
 		snd_card_free(card);
 		return err;
 	}		
-	if ((err = snd_emu10k1_fx8010_pcm(emu, 3, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}		
 	if ((err = snd_emu10k1_mixer(emu)) < 0) {
 		snd_card_free(card);
 		return err;
diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
--- a/sound/pci/emu10k1/emufx.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/emu10k1/emufx.c	2004-06-26 17:13:23 -07:00
@@ -405,7 +405,7 @@
 	}
 }
 
-static int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
 						   snd_fx8010_irq_handler_t *handler,
 						   unsigned char gpr_running,
 						   void *private_data,
@@ -438,7 +438,7 @@
 	return 0;
 }
 
-static int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
 						     snd_emu10k1_fx8010_irq_t *irq)
 {
 	snd_emu10k1_fx8010_irq_t *tmp;
@@ -460,312 +460,6 @@
 	}
 	spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
 	kfree(irq);
-	return 0;
-}
-
-/*
- *   PCM streams
- */
-
-#define INITIAL_TRAM_SHIFT     14
-#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
-
-static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
-{
-	snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, private_data, return);
-	snd_pcm_period_elapsed(substream);
-}
-
-static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
-						   unsigned short *dst_right,
-						   unsigned short *src,
-						   unsigned int count,
-						   unsigned int tram_shift)
-{
-	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
-	if ((tram_shift & 1) == 0) {
-		while (count--) {
-			*dst_left-- = *src++;
-			*dst_right-- = *src++;
-		}
-	} else {
-		while (count--) {
-			*dst_right-- = *src++;
-			*dst_left-- = *src++;
-		}
-	}
-}
-
-static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
-						  unsigned int *tram_pos,
-						  unsigned int *tram_shift,
-						  unsigned int tram_size,
-						  unsigned short *src,
-						  unsigned int frames)
-{
-	unsigned int count;
-
-	while (frames > *tram_pos) {
-		count = *tram_pos + 1;
-		snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
-						       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
-						       src, count, *tram_shift);
-		src += count * 2;
-		frames -= count;
-		*tram_pos = (tram_size / 2) - 1;
-		(*tram_shift)++;
-	}
-	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
-					       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
-					       src, frames, *tram_shift++);
-	*tram_pos -= frames;
-}
-
-static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - pcm->appl_ptr;
-	snd_pcm_uframes_t buffer_size = pcm->buffer_size / 2;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		pcm->sw_ready += diff;
-		pcm->appl_ptr = appl_ptr;
-	}
-	while (pcm->hw_ready < buffer_size &&
-	       pcm->sw_ready > 0) {
-	       	size_t hw_to_end = buffer_size - pcm->hw_data;
-	       	size_t sw_to_end = (runtime->buffer_size << 2) - pcm->sw_data;
-	       	size_t tframes = buffer_size - pcm->hw_ready;
-	       	if (pcm->sw_ready < tframes)
-	       		tframes = pcm->sw_ready;
-	       	if (hw_to_end < tframes)
-	       		tframes = hw_to_end;
-	       	if (sw_to_end < tframes)
-	       		tframes = sw_to_end;
-	       	snd_emu10k1_fx8010_playback_tram_poke(emu, &pcm->tram_pos, &pcm->tram_shift,
-	       					      pcm->buffer_size,
-	       					      (unsigned short *)(runtime->dma_area + (pcm->sw_data << 2)),
-	       					      tframes);
-		pcm->hw_data += tframes;
-		if (pcm->hw_data == buffer_size)
-			pcm->hw_data = 0;
-		pcm->sw_data += tframes;
-		if (pcm->sw_data == runtime->buffer_size)
-			pcm->sw_data = 0;
-		pcm->hw_ready += tframes;
-		pcm->sw_ready -= tframes;
-	}
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
-						 snd_pcm_hw_params_t * hw_params)
-{
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned int i;
-
-	for (i = 0; i < pcm->channels; i++)
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned int i;
-	
-	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
-	pcm->sw_data = pcm->sw_io = pcm->sw_ready = 0;
-	pcm->hw_data = pcm->hw_io = pcm->hw_ready = 0;
-	pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
-	pcm->tram_shift = 0;
-	pcm->appl_ptr = 0;
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);	/* reset */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);	/* reset */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);		/* reset ptr number */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
-	for (i = 0; i < pcm->channels; i++)
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned long flags;
-	int result = 0;
-
-	spin_lock_irqsave(&emu->reg_lock, flags);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* follow thru */
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-#ifdef EMU10K1_SET_AC3_IEC958
-	{
-		int i;
-		for (i = 0; i < 3; i++) {
-			unsigned int bits;
-			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
-			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
-			       0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
-			snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
-		}
-	}
-#endif
-		result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
-		if (result < 0)
-			goto __err;
-		snd_emu10k1_fx8010_playback_transfer(substream);	/* roll the ball */
-		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
-		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
-		pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
-		pcm->tram_shift = 0;
-		break;
-	default:
-		result = -EINVAL;
-		break;
-	}
-      __err:
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
-	return result;
-}
-
-static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	size_t ptr;
-	snd_pcm_sframes_t frames;
-
-	if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
-		return 0;
-	ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0);
-	frames = ptr - pcm->hw_io;
-	if (frames < 0)
-		frames += runtime->buffer_size;
-	pcm->hw_io = ptr;
-	pcm->hw_ready -= frames;
-	pcm->sw_io += frames;
-	if (pcm->sw_io >= runtime->buffer_size)
-		pcm->sw_io -= runtime->buffer_size;
-	snd_emu10k1_fx8010_playback_transfer(substream);
-	return pcm->sw_io;
-}
-
-static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
-{
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
-	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_48000,
-	.rate_min =		48000,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		1,
-	.buffer_bytes_max =	(128*1024),
-	.period_bytes_min =	1024,
-	.period_bytes_max =	(128*1024),
-	.periods_min =		1,
-	.periods_max =		1024,
-	.fifo_size =		0,
-};
-
-static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-
-	runtime->hw = snd_emu10k1_fx8010_playback;
-	runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
-	runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
-	spin_lock(&emu->reg_lock);
-	if (pcm->valid == 0) {
-		spin_unlock(&emu->reg_lock);
-		return -ENODEV;
-	}
-	pcm->opened = 1;
-	spin_unlock(&emu->reg_lock);
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-
-	spin_lock(&emu->reg_lock);
-	pcm->opened = 0;
-	spin_unlock(&emu->reg_lock);
-	return 0;
-}
-
-static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
-	.open =			snd_emu10k1_fx8010_playback_open,
-	.close =		snd_emu10k1_fx8010_playback_close,
-	.ioctl =		snd_pcm_lib_ioctl,
-	.hw_params =		snd_emu10k1_fx8010_playback_hw_params,
-	.hw_free =		snd_emu10k1_fx8010_playback_hw_free,
-	.prepare =		snd_emu10k1_fx8010_playback_prepare,
-	.trigger =		snd_emu10k1_fx8010_playback_trigger,
-	.pointer =		snd_emu10k1_fx8010_playback_pointer,
-	.ack =			snd_emu10k1_fx8010_playback_transfer,
-};
-
-static void snd_emu10k1_fx8010_pcm_free(snd_pcm_t *pcm)
-{
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
-	emu->pcm_fx8010 = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
-{
-	snd_pcm_t *pcm;
-	int err;
-
-	if (rpcm)
-		*rpcm = NULL;
-
-	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 8, 0, &pcm)) < 0)
-		return err;
-
-	pcm->private_data = emu;
-	pcm->private_free = snd_emu10k1_fx8010_pcm_free;
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
-
-	pcm->info_flags = 0;
-	strcpy(pcm->name, "EMU10K1 FX8010");
-	emu->pcm_fx8010 = pcm;
-	
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 0);
-
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/emu10k1/emupcm.c	2004-06-26 17:13:23 -07:00
@@ -1125,6 +1125,276 @@
 	.pointer =		snd_emu10k1_capture_pointer,
 };
 
+
+/* EFX playback */
+
+#define INITIAL_TRAM_SHIFT     14
+#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
+
+static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
+{
+	snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, private_data, return);
+	snd_pcm_period_elapsed(substream);
+}
+
+static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
+						   unsigned short *dst_right,
+						   unsigned short *src,
+						   unsigned int count,
+						   unsigned int tram_shift)
+{
+	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
+	if ((tram_shift & 1) == 0) {
+		while (count--) {
+			*dst_left-- = *src++;
+			*dst_right-- = *src++;
+		}
+	} else {
+		while (count--) {
+			*dst_right-- = *src++;
+			*dst_left-- = *src++;
+		}
+	}
+}
+
+static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
+						  unsigned int *tram_pos,
+						  unsigned int *tram_shift,
+						  unsigned int tram_size,
+						  unsigned short *src,
+						  unsigned int frames)
+{
+	unsigned int count;
+
+	while (frames > *tram_pos) {
+		count = *tram_pos + 1;
+		snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
+						       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
+						       src, count, *tram_shift);
+		src += count * 2;
+		frames -= count;
+		*tram_pos = (tram_size / 2) - 1;
+		(*tram_shift)++;
+	}
+	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
+					       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
+					       src, frames, *tram_shift++);
+	*tram_pos -= frames;
+}
+
+static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
+	snd_pcm_sframes_t diff = appl_ptr - pcm->appl_ptr;
+	snd_pcm_uframes_t buffer_size = pcm->buffer_size / 2;
+
+	if (diff) {
+		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
+			diff += runtime->boundary;
+		pcm->sw_ready += diff;
+		pcm->appl_ptr = appl_ptr;
+	}
+	while (pcm->hw_ready < buffer_size &&
+	       pcm->sw_ready > 0) {
+	       	size_t hw_to_end = buffer_size - pcm->hw_data;
+	       	size_t sw_to_end = (runtime->buffer_size << 2) - pcm->sw_data;
+	       	size_t tframes = buffer_size - pcm->hw_ready;
+	       	if (pcm->sw_ready < tframes)
+	       		tframes = pcm->sw_ready;
+	       	if (hw_to_end < tframes)
+	       		tframes = hw_to_end;
+	       	if (sw_to_end < tframes)
+	       		tframes = sw_to_end;
+	       	snd_emu10k1_fx8010_playback_tram_poke(emu, &pcm->tram_pos, &pcm->tram_shift,
+	       					      pcm->buffer_size,
+	       					      (unsigned short *)(runtime->dma_area + (pcm->sw_data << 2)),
+	       					      tframes);
+		pcm->hw_data += tframes;
+		if (pcm->hw_data == buffer_size)
+			pcm->hw_data = 0;
+		pcm->sw_data += tframes;
+		if (pcm->sw_data == runtime->buffer_size)
+			pcm->sw_data = 0;
+		pcm->hw_ready += tframes;
+		pcm->sw_ready -= tframes;
+	}
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
+						 snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int i;
+
+	for (i = 0; i < pcm->channels; i++)
+		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int i;
+	
+	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
+	pcm->sw_data = pcm->sw_io = pcm->sw_ready = 0;
+	pcm->hw_data = pcm->hw_io = pcm->hw_ready = 0;
+	pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+	pcm->tram_shift = 0;
+	pcm->appl_ptr = 0;
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);	/* reset */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);	/* reset */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);		/* reset ptr number */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
+	for (i = 0; i < pcm->channels; i++)
+		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned long flags;
+	int result = 0;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* follow thru */
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+#ifdef EMU10K1_SET_AC3_IEC958
+	{
+		int i;
+		for (i = 0; i < 3; i++) {
+			unsigned int bits;
+			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
+			       0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
+			snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
+		}
+	}
+#endif
+		result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
+		if (result < 0)
+			goto __err;
+		snd_emu10k1_fx8010_playback_transfer(substream);	/* roll the ball */
+		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
+		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
+		pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+		pcm->tram_shift = 0;
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+      __err:
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return result;
+}
+
+static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	size_t ptr;
+	snd_pcm_sframes_t frames;
+
+	if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
+		return 0;
+	ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0);
+	frames = ptr - pcm->hw_io;
+	if (frames < 0)
+		frames += runtime->buffer_size;
+	pcm->hw_io = ptr;
+	pcm->hw_ready -= frames;
+	pcm->sw_io += frames;
+	if (pcm->sw_io >= runtime->buffer_size)
+		pcm->sw_io -= runtime->buffer_size;
+	snd_emu10k1_fx8010_playback_transfer(substream);
+	return pcm->sw_io;
+}
+
+static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
+	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		1,
+	.channels_max =		1,
+	.buffer_bytes_max =	(128*1024),
+	.period_bytes_min =	1024,
+	.period_bytes_max =	(128*1024),
+	.periods_min =		1,
+	.periods_max =		1024,
+	.fifo_size =		0,
+};
+
+static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	runtime->hw = snd_emu10k1_fx8010_playback;
+	runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
+	runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
+	spin_lock(&emu->reg_lock);
+	if (pcm->valid == 0) {
+		spin_unlock(&emu->reg_lock);
+		return -ENODEV;
+	}
+	pcm->opened = 1;
+	spin_unlock(&emu->reg_lock);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	spin_lock(&emu->reg_lock);
+	pcm->opened = 0;
+	spin_unlock(&emu->reg_lock);
+	return 0;
+}
+
+static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
+	.open =			snd_emu10k1_fx8010_playback_open,
+	.close =		snd_emu10k1_fx8010_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_emu10k1_fx8010_playback_hw_params,
+	.hw_free =		snd_emu10k1_fx8010_playback_hw_free,
+	.prepare =		snd_emu10k1_fx8010_playback_prepare,
+	.trigger =		snd_emu10k1_fx8010_playback_trigger,
+	.pointer =		snd_emu10k1_fx8010_playback_pointer,
+	.ack =			snd_emu10k1_fx8010_playback_transfer,
+};
+
 static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
 {
 	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
@@ -1140,12 +1410,13 @@
 	if (rpcm)
 		*rpcm = NULL;
 
-	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 0, 1, &pcm)) < 0)
+	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
 		return err;
 
 	pcm->private_data = emu;
 	pcm->private_free = snd_emu10k1_pcm_efx_free;
 
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
 
 	pcm->info_flags = 0;
diff -Nru a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
--- a/sound/pci/emu10k1/memory.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/emu10k1/memory.c	2004-06-26 17:13:23 -07:00
@@ -291,7 +291,7 @@
 snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	struct snd_sg_buf *sgbuf = runtime->dma_private;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	snd_util_memhdr_t *hdr;
 	emu10k1_memblk_t *blk;
 	int page, err, idx;
diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c
--- a/sound/pci/es1968.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/es1968.c	2004-06-26 17:13:23 -07:00
@@ -522,9 +522,7 @@
 
 /* DMA Hack! */
 struct snd_esm_memory {
-	char *buf;
-	unsigned long addr;
-	int size;
+	struct snd_dma_buffer buf;
 	int empty;	/* status */
 	struct list_head list;
 };
@@ -1078,10 +1076,10 @@
 	for (channel = 0; channel <= high_apu; channel++) {
 		apu = es->apu[channel];
 
-		snd_es1968_program_wavecache(chip, es, channel, es->memory->addr, 0);
+		snd_es1968_program_wavecache(chip, es, channel, es->memory->buf.addr, 0);
 
 		/* Offset to PCMBAR */
-		pa = es->memory->addr;
+		pa = es->memory->buf.addr;
 		pa -= chip->dma.addr;
 		pa >>= 1;	/* words */
 
@@ -1230,20 +1228,20 @@
 	/* input mixer (left/mono) */
 	/* parallel in crap, see maestro reg 0xC [8-11] */
 	init_capture_apu(chip, es, 2,
-			 es->mixbuf->addr, ESM_MIXBUF_SIZE/4, /* in words */
+			 es->mixbuf->buf.addr, ESM_MIXBUF_SIZE/4, /* in words */
 			 ESM_APU_INPUTMIXER, 0x14);
 	/* SRC (left/mono); get input from inputing apu */
-	init_capture_apu(chip, es, 0, es->memory->addr, size,
+	init_capture_apu(chip, es, 0, es->memory->buf.addr, size,
 			 ESM_APU_SRCONVERTOR, es->apu[2]);
 	if (es->fmt & ESS_FMT_STEREO) {
 		/* input mixer (right) */
 		init_capture_apu(chip, es, 3,
-				 es->mixbuf->addr + ESM_MIXBUF_SIZE/2,
+				 es->mixbuf->buf.addr + ESM_MIXBUF_SIZE/2,
 				 ESM_MIXBUF_SIZE/4, /* in words */
 				 ESM_APU_INPUTMIXER, 0x15);
 		/* SRC (right) */
 		init_capture_apu(chip, es, 1,
-				 es->memory->addr + size*2, size,
+				 es->memory->buf.addr + size*2, size,
 				 ESM_APU_SRCONVERTOR, es->apu[3]);
 	}
 
@@ -1408,8 +1406,8 @@
 	down(&chip->memory_mutex);
 	list_for_each(p, &chip->buf_list) {
 		esm_memory_t *buf = list_entry(p, esm_memory_t, list);
-		if (buf->empty && buf->size > max_size)
-			max_size = buf->size;
+		if (buf->empty && buf->buf.bytes > max_size)
+			max_size = buf->buf.bytes;
 	}
 	up(&chip->memory_mutex);
 	if (max_size >= 128*1024)
@@ -1427,24 +1425,25 @@
 	down(&chip->memory_mutex);
 	list_for_each(p, &chip->buf_list) {
 		buf = list_entry(p, esm_memory_t, list);
-		if (buf->empty && buf->size >= size)
+		if (buf->empty && buf->buf.bytes >= size)
 			goto __found;
 	}
 	up(&chip->memory_mutex);
 	return NULL;
 
 __found:
-	if (buf->size > size) {
+	if (buf->buf.bytes > size) {
 		esm_memory_t *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
 		if (chunk == NULL) {
 			up(&chip->memory_mutex);
 			return NULL;
 		}
-		chunk->size = buf->size - size;
-		chunk->buf = buf->buf + size;
-		chunk->addr = buf->addr + size;
+		chunk->buf = buf->buf;
+		chunk->buf.bytes -= size;
+		chunk->buf.area += size;
+		chunk->buf.addr += size;
 		chunk->empty = 1;
-		buf->size = size;
+		buf->buf.bytes = size;
 		list_add(&chunk->list, &buf->list);
 	}
 	buf->empty = 0;
@@ -1462,7 +1461,7 @@
 	if (buf->list.prev != &chip->buf_list) {
 		chunk = list_entry(buf->list.prev, esm_memory_t, list);
 		if (chunk->empty) {
-			chunk->size += buf->size;
+			chunk->buf.bytes += buf->buf.bytes;
 			list_del(&buf->list);
 			kfree(buf);
 			buf = chunk;
@@ -1471,7 +1470,7 @@
 	if (buf->list.next != &chip->buf_list) {
 		chunk = list_entry(buf->list.next, esm_memory_t, list);
 		if (chunk->empty) {
-			buf->size += chunk->size;
+			buf->buf.bytes += chunk->buf.bytes;
 			list_del(&chunk->list);
 			kfree(chunk);
 		}
@@ -1525,9 +1524,10 @@
 		return -ENOMEM;
 	}
 	memset(chip->dma.area, 0, ESM_MEM_ALIGN);
-	chunk->buf = chip->dma.area + ESM_MEM_ALIGN;
-	chunk->addr = chip->dma.addr + ESM_MEM_ALIGN;
-	chunk->size = chip->dma.bytes - ESM_MEM_ALIGN;
+	chunk->buf = chip->dma;
+	chunk->buf.area += ESM_MEM_ALIGN;
+	chunk->buf.addr += ESM_MEM_ALIGN;
+	chunk->buf.bytes -= ESM_MEM_ALIGN;
 	chunk->empty = 1;
 	list_add(&chunk->list, &chip->buf_list);
 
@@ -1545,7 +1545,7 @@
 	int size = params_buffer_bytes(hw_params);
 
 	if (chan->memory) {
-		if (chan->memory->size >= size) {
+		if (chan->memory->buf.bytes >= size) {
 			runtime->dma_bytes = size;
 			return 0;
 		}
@@ -1556,9 +1556,7 @@
 		// snd_printd("cannot allocate dma buffer: size = %d\n", size);
 		return -ENOMEM;
 	}
-	runtime->dma_bytes = size;
-	runtime->dma_area = chan->memory->buf;
-	runtime->dma_addr = chan->memory->addr;
+	snd_pcm_set_runtime_buffer(substream, &chan->memory->buf);
 	return 1; /* area was changed */
 }
 
@@ -1637,6 +1635,8 @@
 	es->substream = substream;
 	es->mode = ESM_MODE_PLAY;
 
+	substream->dma_device = chip->dma_dev; /* for mmap */
+
 	runtime->private_data = es;
 	runtime->hw = snd_es1968_playback;
 	runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
@@ -1695,7 +1695,9 @@
 		snd_magic_kfree(es);
                 return -ENOMEM;
         }
-	memset(es->mixbuf->buf, 0, ESM_MIXBUF_SIZE);
+	memset(es->mixbuf->buf.area, 0, ESM_MIXBUF_SIZE);
+
+	substream->dma_device = chip->dma_dev; /* for mmap */
 
 	runtime->private_data = es;
 	runtime->hw = snd_es1968_capture;
@@ -1800,11 +1802,11 @@
 		return;
 	}
 
-	memset(memory->buf, 0, CLOCK_MEASURE_BUFSIZE);
+	memset(memory->buf.area, 0, CLOCK_MEASURE_BUFSIZE);
 
-	wave_set_register(chip, apu << 3, (memory->addr - 0x10) & 0xfff8);
+	wave_set_register(chip, apu << 3, (memory->buf.addr - 0x10) & 0xfff8);
 
-	pa = (unsigned int)((memory->addr - chip->dma.addr) >> 1);
+	pa = (unsigned int)((memory->buf.addr - chip->dma.addr) >> 1);
 	pa |= 0x00400000;	/* System RAM (Bit 22) */
 
 	/* initialize apu */
@@ -2470,6 +2472,8 @@
 		outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
 	}
 
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 #ifdef SUPPORT_JOYSTICK
 	if (chip->res_joystick) {
 		gameport_unregister_port(&chip->gameport);
@@ -2484,8 +2488,6 @@
 		release_resource(chip->res_io_port);
 		kfree_nocheck(chip->res_io_port);
 	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
 	snd_magic_kfree(chip);
 	return 0;
 }
diff -Nru a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
--- a/sound/pci/ice1712/Makefile	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ice1712/Makefile	2004-06-26 17:13:23 -07:00
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff -Nru a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
--- a/sound/pci/ice1712/ice1724.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/ice1712/ice1724.c	2004-06-26 17:13:23 -07:00
@@ -44,6 +44,7 @@
 #include "amp.h"
 #include "revo.h"
 #include "aureon.h"
+#include "vt1720_mobo.h"
 
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -54,6 +55,7 @@
 	       REVO_DEVICE_DESC
 	       AMP_AUDIO2000_DEVICE_DESC
 	       AUREON_DEVICE_DESC
+	       VT1720_MOBO_DEVICE_DESC
 		"{VIA,VT1720},"
 		"{VIA,VT1724},"
 		"{ICEnsemble,Generic ICE1724},"
@@ -419,7 +421,7 @@
 	ice->cur_rate = rate;
 
 	/* check MT02 */
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) {
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
 		if (rate > 96000)
 			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
@@ -446,15 +448,6 @@
 		if (ice->akm[i].ops.set_rate_val)
 			ice->akm[i].ops.set_rate_val(&ice->akm[i], rate);
 	}
-
-	/* set up AC97 registers if needed */
-	if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) && ice->ac97) {
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_FRONT_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_SURR_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_LFE_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_SPDIF, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, rate);
-	}
 }
 
 static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
@@ -698,7 +691,7 @@
 static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) {
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		/* I2S */
 		if (ice->eeprom.data[ICE_EEP2_I2S] & 0x08)
 			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192);
@@ -714,15 +707,9 @@
 			ratec = AC97_RATES_FRONT_DAC;
 		else
 			ratec = AC97_RATES_ADC;
-		runtime->hw.rates = ice->ac97->rates[ratec];
 		runtime->hw.rate_max = 48000;
-		if (runtime->hw.rates == SNDRV_PCM_RATE_48000) {
-			runtime->hw.rate_min = 48000;
-			return 0;
-		} else {
-			runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
-			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
-		}
+		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
+		return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
 	}
 	return 0;
 }
@@ -864,8 +851,45 @@
 	.pause = VT1724_RDMA1_PAUSE,
 };
 
+/* update spdif control bits; call with reg_lock */
+static void update_spdif_bits(ice1712_t *ice, unsigned int val)
+{
+	unsigned char cbit, disabled;
+
+	cbit = inb(ICEREG1724(ice, SPDIF_CFG));
+	disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;
+	if (cbit != disabled)
+		outb(disabled, ICEREG1724(ice, SPDIF_CFG));
+	outw(val, ICEMT1724(ice, SPDIF_CTRL));
+	if (cbit != disabled)
+		outb(cbit, ICEREG1724(ice, SPDIF_CFG));
+	outw(val, ICEMT1724(ice, SPDIF_CTRL));
+}
+
+/* update SPDIF control bits according to the given rate */
+static void update_spdif_rate(ice1712_t *ice, unsigned int rate)
+{
+	unsigned int val, nval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ice->reg_lock, flags);
+	nval = val = inw(ICEMT1724(ice, SPDIF_CTRL));
+	nval &= ~(7 << 12);
+	switch (rate) {
+	case 44100: break;
+	case 48000: nval |= 2 << 12; break;
+	case 32000: nval |= 3 << 12; break;
+	}
+	if (val != nval)
+		update_spdif_bits(ice, nval);
+	spin_unlock_irqrestore(&ice->reg_lock, flags);
+}
+
 static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream)
 {
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	if (! ice->force_pdma4)
+		update_spdif_rate(ice, substream->runtime->rate);
 	return snd_vt1724_pcm_prepare(substream, &vt1724_playback_spdif_reg);
 }
 
@@ -1274,7 +1298,7 @@
 		}
 	} else {
 		/* consumer */
-		val |= diga->status[0] & 0x04; /* copyright */
+		val |= diga->status[1] & 0x04; /* copyright */
 		if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS)== IEC958_AES0_CON_EMPHASIS_5015)
 			val |= 1U << 3;
 		val |= (unsigned int)(diga->status[1] & 0x3f) << 4; /* category */
@@ -1331,16 +1355,8 @@
 	val = encode_spdif_bits(&ucontrol->value.iec958);
 	spin_lock_irqsave(&ice->reg_lock, flags);
 	old = inw(ICEMT1724(ice, SPDIF_CTRL));
-	if (val != old) {
-		unsigned char cbit, disabled;
-		cbit = inb(ICEREG1724(ice, SPDIF_CFG));
-		disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;
-		if (cbit != disabled)
-			outb(disabled, ICEREG1724(ice, SPDIF_CFG));
-		outw(val, ICEMT1724(ice, SPDIF_CTRL));
-		if (cbit != disabled)
-			outb(cbit, ICEREG1724(ice, SPDIF_CFG));
-	}
+	if (val != old)
+		update_spdif_bits(ice, val);
 	spin_unlock_irqrestore(&ice->reg_lock, flags);
 	return (val != old);
 }
@@ -1815,6 +1831,7 @@
 	snd_vt1724_revo_cards,
 	snd_vt1724_amp_cards, 
 	snd_vt1724_aureon_cards,
+	snd_vt1720_mobo_cards,
 	0,
 };
 
@@ -1929,9 +1946,6 @@
 	snd_vt1724_set_gpio_data(ice, ice->eeprom.gpiostate);
 
 	outb(0, ICEREG1724(ice, POWERDOWN));
-
-	/* read back to check the availability of SPDIF out */
-	ice->eeprom.data[ICE_EEP2_SPDIF] = inb(ICEREG1724(ice, SPDIF_CFG));
 
 	return 0;
 }
diff -Nru a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/vt1720_mobo.c	2004-06-26 17:13:23 -07:00
@@ -0,0 +1,97 @@
+/*
+ *   ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT)
+ *
+ *   Lowlevel functions for VT1720-based motherboards
+ *
+ *	Copyright (c) 2004 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 <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "vt1720_mobo.h"
+
+
+static int __devinit k8x800_init(ice1712_t *ice)
+{
+	ice->vt1720 = 1;
+
+	/* VT1616 codec */
+	ice->num_total_dacs = 6;
+	ice->num_total_adcs = 2;
+
+	/* WM8728 codec */
+	/* FIXME: TODO */
+
+	return 0;
+}
+
+static int __devinit k8x800_add_controls(ice1712_t *ice)
+{
+	/* FIXME: needs some quirks for VT1616? */
+	return 0;
+}
+
+/* EEPROM image */
+
+static unsigned char k8x800_eeprom[] __devinitdata = {
+	0x01,	/* SYSCONF: clock 256, 1ADC, 2DACs */
+	0x02,	/* ACLINK: ACLINK, packed */
+	0x00,	/* I2S: - */
+	0x00,	/* SPDIF: - */
+	0xff,	/* GPIO_DIR */
+	0xff,	/* GPIO_DIR1 */
+	0x00,	/* - */
+	0xff,	/* GPIO_MASK */
+	0xff,	/* GPIO_MASK1 */
+	0x00,	/* - */
+	0x00,	/* GPIO_STATE */
+	0x00,	/* GPIO_STATE1 */
+	0x00,	/* - */
+};
+
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+	{
+		.subvendor = VT1720_SUBDEVICE_K8X800,
+		.name = "Albatron K8X800 Pro II",
+		.model = "k8x800",
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
+	{
+		.subvendor = VT1720_SUBDEVICE_ZNF3_150,
+		.name = "Chaintech ZNF3-150",
+		/* identical with k8x800 */
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
+	{ } /* terminator */
+};
+
diff -Nru a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/vt1720_mobo.h	2004-06-26 17:13:23 -07:00
@@ -0,0 +1,35 @@
+#ifndef __SOUND_VT1720_MOBO_H
+#define __SOUND_VT1720_MOBO_H
+
+/*
+ *   ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT)
+ *
+ *   Lowlevel functions for VT1720-based motherboards
+ *
+ *	Copyright (c) 2004 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
+ *
+ */      
+
+#define VT1720_MOBO_DEVICE_DESC        "{Albatron,K8X800 Pro II},"\
+				       "{Chaintech,ZNF3-150},"
+
+#define VT1720_SUBDEVICE_K8X800		0xf217052c
+#define VT1720_SUBDEVICE_ZNF3_150	0x0f2741f6
+
+extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
+
+#endif /* __SOUND_VT1720_MOBO_H */
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/intel8x0.c	2004-06-26 17:13:23 -07:00
@@ -149,6 +149,9 @@
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO	0x008a
+#endif
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
 #endif
@@ -463,6 +466,7 @@
 	{ 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7012 */
 	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE */
 	{ 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE2 */
+	{ 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8 */
 	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
 	{ 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8S */
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
@@ -1058,17 +1062,23 @@
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
 	ichdev_t *ichdev = get_ichdev(substream);
-	unsigned long flags;
 	size_t ptr1, ptr;
+	int civ, timeout = 10;
+	unsigned int position;
 
-	ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
-	if (ptr1 != 0)
-		ptr = ichdev->fragsize1 - ptr1;
-	else
-		ptr = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	ptr += ichdev->position;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	do {
+		civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
+		ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
+		position = ichdev->position;
+		if (ptr1 == 0)
+			udelay(1);
+		if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
+		    ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+			break;
+	} while (timeout--);
+	ptr1 <<= ichdev->pos_shift;
+	ptr = ichdev->fragsize1 - ptr1;
+	ptr += position;
 	if (ptr >= ichdev->size)
 		return 0;
 	return bytes_to_frames(substream->runtime, ptr);
@@ -2614,6 +2624,7 @@
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
 	{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
+	{ PCI_DEVICE_ID_NVIDIA_CK8_AUDIO, "NVidia CK8" },
 	{ 0x746d, "AMD AMD8111" },
 	{ 0x7445, "AMD AMD768" },
 	{ 0x5455, "ALi M5455" },
diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
--- a/sound/pci/korg1212/korg1212.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/korg1212/korg1212.c	2004-06-26 17:13:23 -07:00
@@ -1414,13 +1414,14 @@
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", stateName[korg1212->cardState]);
 #endif
 
+	substream->dma_device = korg1212->dma_dev; /* set for mmap */
+
         snd_pcm_set_sync(substream);    // ???
 
 	snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_playback_info;
-	runtime->dma_area = (char *) korg1212->playDataBufsPtr;
-	runtime->dma_bytes = K1212_BUF_SIZE;
+	snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1445,13 +1446,14 @@
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", stateName[korg1212->cardState]);
 #endif
 
+	substream->dma_device = korg1212->dma_dev; /* set for mmap */
+
         snd_pcm_set_sync(substream);    // ???
 
 	snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_capture_info;
-	runtime->dma_area = (char *) korg1212->recordDataBufsPtr;
-	runtime->dma_bytes = K1212_BUF_SIZE;
+	snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
diff -Nru a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
--- a/sound/pci/mixart/mixart.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/mixart/mixart.c	2004-06-26 17:13:23 -07:00
@@ -247,21 +247,27 @@
 	/* pipe is not yet defined */
 	if( pipe->status == PIPE_UNDEFINED ) {
 		int err, i;
-		mixart_streaming_group_t streaming_group_resp;
-		mixart_streaming_group_req_t streaming_group_req;
+		struct {
+			mixart_streaming_group_req_t sgroup_req;
+			mixart_streaming_group_t sgroup_resp;
+		} *buf;
 
 		snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number);
 
+		buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+		if (!buf)
+			return NULL;
+
 		request.uid = (mixart_uid_t){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
-		request.data = &streaming_group_req;
-		request.size = sizeof(streaming_group_req);
+		request.data = &buf->sgroup_req;
+		request.size = sizeof(buf->sgroup_req);
 
-		memset(&streaming_group_req, 0, sizeof(streaming_group_req));
+		memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
 
-		streaming_group_req.stream_count = stream_count;
-		streaming_group_req.channel_count = 2;
-		streaming_group_req.latency = 256;
-		streaming_group_req.connector = pipe->uid_left_connector;  /* the left connector */
+		buf->sgroup_req.stream_count = stream_count;
+		buf->sgroup_req.channel_count = 2;
+		buf->sgroup_req.latency = 256;
+		buf->sgroup_req.connector = pipe->uid_left_connector;  /* the left connector */
 
 		for (i=0; i<stream_count; i++) {
 			int j;
@@ -269,15 +275,15 @@
 			struct mixart_bufferinfo *bufferinfo;
 			
 			/* we don't yet know the format, so config 16 bit pcm audio for instance */
-			streaming_group_req.stream_info[i].size_max_byte_frame = 1024;
-			streaming_group_req.stream_info[i].size_max_sample_frame = 256;
-			streaming_group_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
+			buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
+			buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
+			buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
 
 			/* find the right bufferinfo_array */
 			j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
 			if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
 
-			streaming_group_req.flow_entry[i] = j;
+			buf->sgroup_req.flow_entry[i] = j;
 
 			flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
 			flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(mixart_bufferinfo_t));
@@ -294,17 +300,19 @@
 			}
 		}
 
-		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(streaming_group_resp), &streaming_group_resp);
-		if((err < 0) || (streaming_group_resp.status != 0)) {
-			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, streaming_group_resp.status);
+		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
+		if((err < 0) || (buf->sgroup_resp.status != 0)) {
+			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status);
+			kfree(buf);
 			return NULL;
 		}
 
-		pipe->group_uid = streaming_group_resp.group;     /* id of the pipe, as returned by embedded */
-		pipe->stream_count = streaming_group_resp.stream_count;
-		/* pipe->stream_uid[i] = streaming_group_resp.stream[i].stream_uid; */
+		pipe->group_uid = buf->sgroup_resp.group;     /* id of the pipe, as returned by embedded */
+		pipe->stream_count = buf->sgroup_resp.stream_count;
+		/* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
 
 		pipe->status = PIPE_STOPPED;
+		kfree(buf);
 	}
 
 	if(monitoring)	pipe->monitoring = 1;
diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
--- a/sound/pci/nm256/nm256.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/nm256/nm256.c	2004-06-26 17:13:23 -07:00
@@ -660,9 +660,9 @@
 	return bytes_to_frames(substream->runtime, curp);
 }
 
+/* Remapped I/O space can be accessible as pointer on i386 */
+/* This might be changed in the future */
 #ifndef __i386__
-/* FIXME: I/O space is not accessible via pointers on all architectures */
-
 /*
  * silence / copy for playback
  */
@@ -757,10 +757,8 @@
  */
 static snd_pcm_hardware_t snd_nm256_playback =
 {
-	.info =
-#ifdef __i386__
-				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
-#endif
+	.info =			SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
+				SNDRV_PCM_INFO_MMAP_IOMEM|
 				SNDRV_PCM_INFO_INTERLEAVED |
 				/*SNDRV_PCM_INFO_PAUSE |*/
 				SNDRV_PCM_INFO_RESUME,
@@ -779,10 +777,8 @@
 
 static snd_pcm_hardware_t snd_nm256_capture =
 {
-	.info =
-#ifdef __i386__
-				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
-#endif
+	.info =			SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
+				SNDRV_PCM_INFO_MMAP_IOMEM|
 				SNDRV_PCM_INFO_INTERLEAVED |
 				/*SNDRV_PCM_INFO_PAUSE |*/
 				SNDRV_PCM_INFO_RESUME,
diff -Nru a/sound/pci/rme32.c b/sound/pci/rme32.c
--- a/sound/pci/rme32.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/rme32.c	2004-06-26 17:13:23 -07:00
@@ -213,10 +213,6 @@
 	size_t playback_periodsize;	/* in bytes, zero if not used */
 	size_t capture_periodsize;	/* in bytes, zero if not used */
 
-	snd_pcm_uframes_t playback_last_appl_ptr;
-	size_t playback_ptr;
-	size_t capture_ptr;
-
 	snd_card_t *card;
 	snd_pcm_t *spdif_pcm;
 	snd_pcm_t *adat_pcm;
@@ -329,6 +325,7 @@
 static snd_pcm_hardware_t snd_rme32_playback_spdif_info = {
 	.info =		(SNDRV_PCM_INFO_MMAP |
 			 SNDRV_PCM_INFO_MMAP_VALID |
+			 SNDRV_PCM_INFO_MMAP_IOMEM |
 			 SNDRV_PCM_INFO_INTERLEAVED | 
 			 SNDRV_PCM_INFO_PAUSE),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | 
@@ -354,6 +351,7 @@
 static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
 	.info =		(SNDRV_PCM_INFO_MMAP |
 			 SNDRV_PCM_INFO_MMAP_VALID |
+			 SNDRV_PCM_INFO_MMAP_IOMEM |
 			 SNDRV_PCM_INFO_INTERLEAVED | 
 			 SNDRV_PCM_INFO_PAUSE),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | 
@@ -380,6 +378,7 @@
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
 	.formats=            SNDRV_PCM_FMTBIT_S16_LE,
@@ -404,6 +403,7 @@
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
 	.formats =           SNDRV_PCM_FMTBIT_S16_LE,
@@ -678,10 +678,12 @@
 {
 	int err, rate, dummy;
 	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+	runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
+	runtime->dma_bytes = RME32_BUFFER_SIZE;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream,
-				      params_buffer_bytes(params))) < 0)
-		return err;
 	spin_lock_irq(&rme32->lock);
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
@@ -719,12 +721,6 @@
 	return 0;
 }
 
-static int snd_rme32_playback_hw_free(snd_pcm_substream_t * substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static int
 snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
 			    snd_pcm_hw_params_t * params)
@@ -734,9 +730,10 @@
 	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream,
-				      params_buffer_bytes(params))) < 0)
-		return err;
+	runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+	runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
+	runtime->dma_bytes = RME32_BUFFER_SIZE;
+
 	spin_lock_irqsave(&rme32->lock, flags);
 	/* enable AutoSync for record-preparing */
 	rme32->wcreg |= RME32_WCR_AUTOSYNC;
@@ -780,18 +777,10 @@
 	return 0;
 }
 
-static int snd_rme32_capture_hw_free(snd_pcm_substream_t * substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static void snd_rme32_playback_start(rme32_t * rme32, int from_pause)
 {
 	if (!from_pause) {
 		writel(0, rme32->iobase + RME32_IO_RESET_POS);
-		rme32->playback_last_appl_ptr = 0;
-		rme32->playback_ptr = 0;
 	}
 
 	rme32->wcreg |= RME32_WCR_START;
@@ -882,8 +871,6 @@
 	rme32->wcreg &= ~RME32_WCR_ADAT;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	rme32->playback_substream = substream;
-	rme32->playback_last_appl_ptr = 0;
-	rme32->playback_ptr = 0;
 	spin_unlock_irqrestore(&rme32->lock, flags);
 
 	runtime->hw = snd_rme32_playback_spdif_info;
@@ -927,7 +914,6 @@
                 return -EBUSY;
         }
 	rme32->capture_substream = substream;
-	rme32->capture_ptr = 0;
 	spin_unlock_irqrestore(&rme32->lock, flags);
 
 	runtime->hw = snd_rme32_capture_spdif_info;
@@ -972,8 +958,6 @@
 	rme32->wcreg |= RME32_WCR_ADAT;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	rme32->playback_substream = substream;
-	rme32->playback_last_appl_ptr = 0;
-	rme32->playback_ptr = 0;
 	spin_unlock_irqrestore(&rme32->lock, flags);
 	
 	runtime->hw = snd_rme32_playback_adat_info;
@@ -1017,7 +1001,6 @@
 		return -EBUSY;
         }
 	rme32->capture_substream = substream;
-	rme32->capture_ptr = 0;
 	spin_unlock_irqrestore(&rme32->lock, flags);
 
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
@@ -1178,36 +1161,6 @@
 snd_rme32_playback_pointer(snd_pcm_substream_t * substream)
 {
 	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff;
-	size_t bytes;
-
-
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		diff = runtime->control->appl_ptr -
-		       rme32->playback_last_appl_ptr;
-		rme32->playback_last_appl_ptr = runtime->control->appl_ptr;
-		if (diff != 0 && diff < -(snd_pcm_sframes_t) (runtime->boundary >> 1)) {
-			diff += runtime->boundary;
-		}
-		bytes = diff << rme32->playback_frlog;
-		if (bytes > RME32_BUFFER_SIZE - rme32->playback_ptr) {
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER + rme32->playback_ptr),
-				    runtime->dma_area + rme32->playback_ptr,
-				    RME32_BUFFER_SIZE - rme32->playback_ptr);
-			bytes -= RME32_BUFFER_SIZE - rme32->playback_ptr;
-			if (bytes > RME32_BUFFER_SIZE) {
-				bytes = RME32_BUFFER_SIZE;
-			}
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER),
-				    runtime->dma_area, bytes);
-			rme32->playback_ptr = bytes;
-		} else if (bytes != 0) {
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER + rme32->playback_ptr),
-				    runtime->dma_area + rme32->playback_ptr, bytes);
-			rme32->playback_ptr += bytes;
-		}
-	}
 	return snd_rme32_playback_ptr(rme32);
 }
 
@@ -1215,31 +1168,7 @@
 snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
 {
 	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t frameptr;
-	size_t ptr;
-
-	frameptr = snd_rme32_capture_ptr(rme32);
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		ptr = frameptr << rme32->capture_frlog;
-		if (ptr > rme32->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER +
-					       rme32->capture_ptr),
-				      ptr - rme32->capture_ptr);
-			rme32->capture_ptr += ptr - rme32->capture_ptr;
-		} else if (ptr < rme32->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER +
-					       rme32->capture_ptr),
-				      RME32_BUFFER_SIZE - rme32->capture_ptr);
-			memcpy_fromio(runtime->dma_area,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER),
-				      ptr);
-			rme32->capture_ptr = ptr;
-		}
-	}
-	return frameptr;
+	return snd_rme32_capture_ptr(rme32);
 }
 
 static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
@@ -1247,7 +1176,6 @@
 	.close =	snd_rme32_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_playback_hw_params,
-	.hw_free =	snd_rme32_playback_hw_free,
 	.prepare =	snd_rme32_playback_prepare,
 	.trigger =	snd_rme32_playback_trigger,
 	.pointer =	snd_rme32_playback_pointer,
@@ -1260,7 +1188,6 @@
 	.close =	snd_rme32_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_capture_hw_params,
-	.hw_free =	snd_rme32_capture_hw_free,
 	.prepare =	snd_rme32_capture_prepare,
 	.trigger =	snd_rme32_capture_trigger,
 	.pointer =	snd_rme32_capture_pointer,
@@ -1272,7 +1199,6 @@
 	.close =	snd_rme32_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_playback_hw_params,
-	.hw_free =	snd_rme32_playback_hw_free,
 	.prepare =	snd_rme32_playback_prepare,
 	.trigger =	snd_rme32_playback_trigger,
 	.pointer =	snd_rme32_playback_pointer,
@@ -1285,7 +1211,6 @@
 	.close =	snd_rme32_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_capture_hw_params,
-	.hw_free =	snd_rme32_capture_hw_free,
 	.prepare =	snd_rme32_capture_prepare,
 	.trigger =	snd_rme32_capture_trigger,
 	.pointer =	snd_rme32_capture_pointer,
@@ -1319,7 +1244,6 @@
 {
 	rme32_t *rme32 = (rme32_t *) pcm->private_data;
 	rme32->spdif_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void
@@ -1327,7 +1251,6 @@
 {
 	rme32_t *rme32 = (rme32_t *) pcm->private_data;
 	rme32->adat_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static int __devinit snd_rme32_create(rme32_t * rme32)
@@ -1376,13 +1299,7 @@
 	snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
 			&snd_rme32_capture_spdif_ops);
 
-	rme32->spdif_pcm->info_flags = 0;
-
-	snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm,
-					      SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data(GFP_KERNEL),
-					      RME32_BUFFER_SIZE,
-					      RME32_BUFFER_SIZE);
+	rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
 
 	/* set up ALSA pcm device for ADAT */
 	if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
@@ -1404,13 +1321,7 @@
 		snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
 				&snd_rme32_capture_adat_ops);
 		
-		rme32->adat_pcm->info_flags = 0;
-
-		snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, 
-						      SNDRV_DMA_TYPE_CONTINUOUS,
-						      snd_dma_continuous_data(GFP_KERNEL),
-						      RME32_BUFFER_SIZE, 
-						      RME32_BUFFER_SIZE);
+		rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
 	}
 
 
diff -Nru a/sound/pci/rme96.c b/sound/pci/rme96.c
--- a/sound/pci/rme96.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/rme96.c	2004-06-26 17:13:23 -07:00
@@ -250,10 +250,6 @@
         size_t playback_periodsize; /* in bytes, zero if not used */
 	size_t capture_periodsize; /* in bytes, zero if not used */
 
-        snd_pcm_uframes_t playback_last_appl_ptr;
-	size_t playback_ptr;
-	size_t capture_ptr;
-
 	snd_card_t         *card;
 	snd_pcm_t          *spdif_pcm;
 	snd_pcm_t          *adat_pcm; 
@@ -394,6 +390,7 @@
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
 	.formats =	     (SNDRV_PCM_FMTBIT_S16_LE |
@@ -423,6 +420,7 @@
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
 	.formats =	     (SNDRV_PCM_FMTBIT_S16_LE |
@@ -452,6 +450,7 @@
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
 	.formats =	     (SNDRV_PCM_FMTBIT_S16_LE |
@@ -477,6 +476,7 @@
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
 	.formats =	     (SNDRV_PCM_FMTBIT_S16_LE |
@@ -993,10 +993,13 @@
 {
 	unsigned long flags;        
 	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, rate, dummy;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params))) < 0)
-		return err;
+	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_PLAY_BUFFER);
+	runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;
+	runtime->dma_bytes = RME96_BUFFER_SIZE;
+
 	spin_lock_irqsave(&rme96->lock, flags);
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
             snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&
@@ -1038,13 +1041,6 @@
 }
 
 static int
-snd_rme96_playback_hw_free(snd_pcm_substream_t *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-static int
 snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
 			    snd_pcm_hw_params_t *params)
 {
@@ -1053,8 +1049,10 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, isadat, rate;
 	
-	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params))) < 0)
-		return err;
+	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_REC_BUFFER);
+	runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;
+	runtime->dma_bytes = RME96_BUFFER_SIZE;
+
 	spin_lock_irqsave(&rme96->lock, flags);
 	if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) {
 		spin_unlock_irqrestore(&rme96->lock, flags);
@@ -1096,21 +1094,12 @@
 	return 0;
 }
 
-static int
-snd_rme96_capture_hw_free(snd_pcm_substream_t *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static void
 snd_rme96_playback_start(rme96_t *rme96,
 			 int from_pause)
 {
 	if (!from_pause) {
 		writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
-		rme96->playback_last_appl_ptr = 0;
-		rme96->playback_ptr = 0;
 	}
 
 	rme96->wcreg |= RME96_WCR_START;
@@ -1123,7 +1112,6 @@
 {
 	if (!from_pause) {
 		writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
-		rme96->capture_ptr = 0;
 	}
 
 	rme96->wcreg |= RME96_WCR_START_2;
@@ -1212,8 +1200,6 @@
 	rme96->wcreg &= ~RME96_WCR_ADAT;
 	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	rme96->playback_substream = substream;
-	rme96->playback_last_appl_ptr = 0;
-	rme96->playback_ptr = 0;
 	spin_unlock_irqrestore(&rme96->lock, flags);
 
 	runtime->hw = snd_rme96_playback_spdif_info;
@@ -1264,7 +1250,6 @@
                 return -EBUSY;
         }
 	rme96->capture_substream = substream;
-	rme96->capture_ptr = 0;
 	spin_unlock_irqrestore(&rme96->lock, flags);
 	
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
@@ -1291,8 +1276,6 @@
 	rme96->wcreg |= RME96_WCR_ADAT;
 	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	rme96->playback_substream = substream;
-	rme96->playback_last_appl_ptr = 0;
-	rme96->playback_ptr = 0;
 	spin_unlock_irqrestore(&rme96->lock, flags);
 	
 	runtime->hw = snd_rme96_playback_adat_info;
@@ -1341,7 +1324,6 @@
                 return -EBUSY;
         }
 	rme96->capture_substream = substream;
-	rme96->capture_ptr = 0;
 	spin_unlock_irqrestore(&rme96->lock, flags);
 
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
@@ -1509,42 +1491,6 @@
 snd_rme96_playback_pointer(snd_pcm_substream_t *substream)
 {
 	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff;
-	size_t bytes;
-	
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		diff = runtime->control->appl_ptr -
-		    rme96->playback_last_appl_ptr;
- 	        rme96->playback_last_appl_ptr = runtime->control->appl_ptr;
-	        if (diff != 0 &&
-		    diff < -(snd_pcm_sframes_t)(runtime->boundary >> 1))
-		{
-		        diff += runtime->boundary;
-		}
-		bytes = diff << rme96->playback_frlog;
-		
-		if (bytes > RME96_BUFFER_SIZE - rme96->playback_ptr) {
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER +
-					     rme96->playback_ptr),
-				    runtime->dma_area + rme96->playback_ptr,
-				    RME96_BUFFER_SIZE - rme96->playback_ptr);
-		        bytes -= RME96_BUFFER_SIZE - rme96->playback_ptr;
-			if (bytes > RME96_BUFFER_SIZE) {
-			        bytes = RME96_BUFFER_SIZE;
-			}
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER),
-				    runtime->dma_area,
-				    bytes);
-			rme96->playback_ptr = bytes;
-		} else if (bytes != 0) {
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER +
-					     rme96->playback_ptr),
-				    runtime->dma_area + rme96->playback_ptr,
-				    bytes);
-			rme96->playback_ptr += bytes;
-		}
-	}
 	return snd_rme96_playback_ptr(rme96);
 }
 
@@ -1552,31 +1498,7 @@
 snd_rme96_capture_pointer(snd_pcm_substream_t *substream)
 {
 	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t frameptr;
-	size_t ptr;
-
-	frameptr = snd_rme96_capture_ptr(rme96);
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		ptr = frameptr << rme96->capture_frlog;
-		if (ptr > rme96->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme96->capture_ptr,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER +
-					       rme96->capture_ptr),
-				      ptr - rme96->capture_ptr);
-			rme96->capture_ptr += ptr - rme96->capture_ptr;
-		} else if (ptr < rme96->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme96->capture_ptr,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER +
-					       rme96->capture_ptr),
-				      RME96_BUFFER_SIZE - rme96->capture_ptr);
-			memcpy_fromio(runtime->dma_area,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER),
-				      ptr);
-			rme96->capture_ptr = ptr;
-		}
-	}
-	return frameptr;
+	return snd_rme96_capture_ptr(rme96);
 }
 
 static snd_pcm_ops_t snd_rme96_playback_spdif_ops = {
@@ -1584,7 +1506,6 @@
 	.close =	snd_rme96_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_playback_hw_params,
-	.hw_free =	snd_rme96_playback_hw_free,
 	.prepare =	snd_rme96_playback_prepare,
 	.trigger =	snd_rme96_playback_trigger,
 	.pointer =	snd_rme96_playback_pointer,
@@ -1597,7 +1518,6 @@
 	.close =	snd_rme96_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_capture_hw_params,
-	.hw_free =	snd_rme96_capture_hw_free,
 	.prepare =	snd_rme96_capture_prepare,
 	.trigger =	snd_rme96_capture_trigger,
 	.pointer =	snd_rme96_capture_pointer,
@@ -1609,7 +1529,6 @@
 	.close =	snd_rme96_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_playback_hw_params,
-	.hw_free =	snd_rme96_playback_hw_free,
 	.prepare =	snd_rme96_playback_prepare,
 	.trigger =	snd_rme96_playback_trigger,
 	.pointer =	snd_rme96_playback_pointer,
@@ -1622,7 +1541,6 @@
 	.close =	snd_rme96_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_capture_hw_params,
-	.hw_free =	snd_rme96_capture_hw_free,
 	.prepare =	snd_rme96_capture_prepare,
 	.trigger =	snd_rme96_capture_trigger,
 	.pointer =	snd_rme96_capture_pointer,
@@ -1661,7 +1579,6 @@
 {
 	rme96_t *rme96 = (rme96_t *) pcm->private_data;
 	rme96->spdif_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void
@@ -1669,7 +1586,6 @@
 {
 	rme96_t *rme96 = (rme96_t *) pcm->private_data;
 	rme96->adat_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static int __devinit
@@ -1719,12 +1635,6 @@
 
 	rme96->spdif_pcm->info_flags = 0;
 
-	snd_pcm_lib_preallocate_pages_for_all(rme96->spdif_pcm,
-					      SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data(GFP_KERNEL),
-					      RME96_BUFFER_SIZE,
-					      RME96_BUFFER_SIZE);
-
 	/* set up ALSA pcm device for ADAT */
 	if (pci->device == PCI_DEVICE_ID_DIGI96) {
 		/* ADAT is not available on the base model */
@@ -1742,12 +1652,6 @@
 		snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops);
 		
 		rme96->adat_pcm->info_flags = 0;
-
-		snd_pcm_lib_preallocate_pages_for_all(rme96->adat_pcm,
-						      SNDRV_DMA_TYPE_CONTINUOUS,
-						      snd_dma_continuous_data(GFP_KERNEL),
-						      RME96_BUFFER_SIZE,
-						      RME96_BUFFER_SIZE);
 	}
 
 	rme96->playback_periodsize = 0;
diff -Nru a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
--- a/sound/pci/trident/trident_memory.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/trident/trident_memory.c	2004-06-26 17:13:23 -07:00
@@ -189,7 +189,7 @@
 	snd_util_memblk_t *blk;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int idx, page;
-	struct snd_sg_buf *sgbuf = runtime->dma_private;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
 	snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
 	hdr = trident->tlb.memhdr;
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c	2004-06-26 17:13:23 -07:00
+++ b/sound/pci/via82xx.c	2004-06-26 17:13:23 -07:00
@@ -725,7 +725,11 @@
 	unsigned int size, res;
 
 	size = viadev->idx_table[idx].size;
-	res = viadev->idx_table[idx].offset + size - count;
+	/* FIXME: is this always true? */
+	if (count)
+		res = viadev->idx_table[idx].offset + size - count;
+	else
+		res = viadev->idx_table[idx].offset;
 
 	/* check the validity of the calculated position */
 	if (size < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))) {
@@ -1035,6 +1039,7 @@
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_RESUME |
 				 SNDRV_PCM_INFO_PAUSE),
 	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
@@ -1060,19 +1065,6 @@
 	int err;
 	unsigned long flags;
 	struct via_rate_lock *ratep;
-	struct ratetbl {
-		int rate;
-		unsigned int bit;
-	} ratebits[] = {
-		{8000, SNDRV_PCM_RATE_8000},
-		{11025, SNDRV_PCM_RATE_11025},
-		{16000, SNDRV_PCM_RATE_16000},
-		{22050, SNDRV_PCM_RATE_22050},
-		{32000, SNDRV_PCM_RATE_32000},
-		{44100, SNDRV_PCM_RATE_44100},
-		{48000, SNDRV_PCM_RATE_48000},
-	};
-	int i;
 
 	runtime->hw = snd_via82xx_hw;
 	
@@ -1080,10 +1072,10 @@
 	ratep = &chip->rates[viadev->direction];
 	spin_lock_irqsave(&ratep->lock, flags);
 	ratep->used++;
-	if (chip->spdif_on) {
-		runtime->hw.rates = SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000;
-		runtime->hw.rate_min = 32000;
-		runtime->hw.rate_max = 48000;
+	if (chip->spdif_on && viadev->reg_offset == 0x30) {
+		/* DXS#3 and spdif is on */
+		runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF];
+		snd_pcm_limit_hw_rates(runtime);
 	} else if (chip->dxs_fixed && viadev->reg_offset < 0x40) {
 		/* fixed DXS playback rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_48000;
@@ -1091,27 +1083,10 @@
 	} else if (! ratep->rate) {
 		int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
 		runtime->hw.rates = chip->ac97->rates[idx];
-		for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) {
-			if (runtime->hw.rates & ratebits[i].bit) {
-				runtime->hw.rate_min = ratebits[i].rate;
-				break;
-			}
-		}
-		for (i = ARRAY_SIZE(ratebits) - 1; i >= 0; i--) {
-			if (runtime->hw.rates & ratebits[i].bit) {
-				runtime->hw.rate_max = ratebits[i].rate;
-				break;
-			}
-		}
+		snd_pcm_limit_hw_rates(runtime);
 	} else {
 		/* a fixed rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-		for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) {
-			if (ratep->rate == ratebits[i].rate) {
-				runtime->hw.rates = ratebits[i].bit;
-				break;
-			}
-		}
 		runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate;
 	}
 	spin_unlock_irqrestore(&ratep->lock, flags);
@@ -1363,6 +1338,10 @@
 							 snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
 		return err;
 
+	/* SPDIF supported? */
+	if (! ac97_can_spdif(chip->ac97))
+		return 0;
+
 	/* PCM #1:  DXS3 playback (for spdif) */
 	err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 0, &pcm);
 	if (err < 0)
@@ -1660,9 +1639,11 @@
 		if (err < 0)
 			return err;
 	}
-	err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));
-	if (err < 0)
-		return err;
+	if (ac97_can_spdif(chip->ac97)) {
+		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));
+		if (err < 0)
+			return err;
+	}
 	if (chip->chip_type != TYPE_VIA8233A) {
 		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
 		if (err < 0)
@@ -1672,6 +1653,7 @@
 	/* select spdif data slot 10/11 */
 	pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);
 	val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011;
+	val &= ~VIA8233_SPDIF_DX3; /* SPDIF off as default */
 	pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val);
 
 	return 0;
@@ -2114,6 +2096,7 @@
 		{ .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
 		{ .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
 		{ .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
+		{ .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
 		{ .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
 		{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
 		{ .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
--- a/sound/usb/usbaudio.c	2004-06-26 17:13:23 -07:00
+++ b/sound/usb/usbaudio.c	2004-06-26 17:13:23 -07:00
@@ -1183,9 +1183,9 @@
 		if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot get freq at ep 0x%x\n",
+			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
 				   dev->devnum, iface, fmt->altsetting, ep);
-			return err;
+			return 0; /* some devices don't support reading */
 		}
 		crate = data[0] | (data[1] << 8) | (data[2] << 16);
 		if (crate != rate) {
@@ -2182,6 +2182,24 @@
 
 
 /*
+ * check if the device uses big-endian samples
+ */
+static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+{
+	/* M-Audio */
+	if (dev->descriptor.idVendor == 0x0763) {
+		/* Quattro: captured data only */
+		if (dev->descriptor.idProduct == 0x2001 &&
+		    fp->endpoint & USB_DIR_IN)
+			return 1;
+		/* Audiophile USB */
+		if (dev->descriptor.idProduct == 0x2003)
+			return 1;
+	}
+	return 0;
+}
+
+/*
  * parse the audio format type I descriptor
  * and returns the corresponding pcm format
  *
@@ -2217,17 +2235,13 @@
 			pcm_format = SNDRV_PCM_FORMAT_S8;
 			break;
 		case 2:
-			/* M-Audio audiophile USB workaround */
-			if (dev->descriptor.idVendor == 0x0763 &&
-			    dev->descriptor.idProduct == 0x2003)
+			if (is_big_endian_format(dev, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
 			break;
 		case 3:
-			/* M-Audio audiophile USB workaround */
-			if (dev->descriptor.idVendor == 0x0763 &&
-			    dev->descriptor.idProduct == 0x2003)
+			if (is_big_endian_format(dev, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
--- a/sound/usb/usbaudio.h	2004-06-26 17:13:23 -07:00
+++ b/sound/usb/usbaudio.h	2004-06-26 17:13:23 -07:00
@@ -205,6 +205,8 @@
 int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
 
 int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
+void snd_usbmidi_input_stop(struct list_head* p);
+void snd_usbmidi_input_start(struct list_head* p);
 void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
 
 /*
diff -Nru a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
--- a/sound/usb/usbmidi.c	2004-06-26 17:13:23 -07:00
+++ b/sound/usb/usbmidi.c	2004-06-26 17:13:23 -07:00
@@ -1145,6 +1145,44 @@
 }
 
 /*
+ * Temporarily stop input. 
+ */
+void snd_usbmidi_input_stop(struct list_head* p)
+{
+	snd_usb_midi_t* umidi;
+	int i;
+
+	umidi = list_entry(p, snd_usb_midi_t, list);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+		snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+		if (ep->in)
+			usb_unlink_urb(ep->in->urb);
+	}
+}
+
+static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
+{
+	if (ep) {
+		struct urb* urb = ep->urb; 
+		urb->dev = ep->umidi->chip->dev;
+		snd_usbmidi_submit_urb(urb, GFP_KERNEL);
+	}
+}
+
+/*
+ * Resume input after a call to snd_usbmidi_input_stop().
+ */
+void snd_usbmidi_input_start(struct list_head* p)
+{
+	snd_usb_midi_t* umidi;
+	int i;
+
+	umidi = list_entry(p, snd_usb_midi_t, list);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
+		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+}
+
+/*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
 int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
@@ -1219,8 +1257,6 @@
 	list_add(&umidi->list, &umidi->chip->midi_list);
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-		if (umidi->endpoints[i].in)
-			snd_usbmidi_submit_urb(umidi->endpoints[i].in->urb,
-					       GFP_KERNEL);
+		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
 	return 0;
 }
diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
--- a/sound/usb/usbquirks.h	2004-06-26 17:13:23 -07:00
+++ b/sound/usb/usbquirks.h	2004-06-26 17:13:23 -07:00
@@ -830,11 +830,42 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "M-Audio",
 		.product_name = "Quattro",
-		.ifnum = 9,
-		.type = QUIRK_MIDI_MIDIMAN,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			/*
+			 * Interfaces 0-2 are "Windows-compatible", 16-bit only,
+			 * and share endpoints with the other interfaces.
+			 * Ignore them.  The other interfaces can do 24 bits,
+			 * but captured samples are big-endian (see usbaudio.c).
+			 */
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 7,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 8,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 9,
+				.type = QUIRK_MIDI_MIDIMAN,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },