http://linux-sound.bkbits.net/linux-sound perex@suse.cz|ChangeSet|20050302140302|12429 perex # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/02 15:03:02+01:00 perex@suse.cz # [ALSA] emu10k1 - fix the initial value for Captured FX8010 Outputs # # EMU10K1/EMU10K2 driver # - rename 'EFX voices mask' to 'Captured FX8010 Outputs' # - fix the initial value # # Signed-off-by: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/emupcm.c # 2005/03/02 01:40:37+01:00 perex@suse.cz +2 -2 # [ALSA] emu10k1 - fix the initial value for Captured FX8010 Outputs # # D:2005/03/02 08:40:37 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emupcm.c:1.40->1.41 # L:- rename 'EFX voices mask' to 'Captured FX8010 Outputs' # L:- fix the initial value # Signed-off-by: Lee Revell # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 15:02:09+01:00 perex@suse.cz # [ALSA] Control API - fix the wrong allocation for userspace controls # # Control Midlevel # # # Signed-off-by: Jaroslav Kysela # # sound/core/control.c # 2005/03/01 02:12:03+01:00 perex@suse.cz +1 -1 # [ALSA] Control API - fix the wrong allocation for userspace controls # # D:2005/03/01 09:12:03 # C:Control Midlevel # F:core/control.c:1.58->1.59 # L: # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 15:01:23+01:00 perex@suse.cz # [ALSA] Fix the Audigy SPDIF sample rate register definitions # # EMU10K1/EMU10K2 driver # # # Signed-off-by: Lee Revell # Signed-off-by: Jaroslav Kysela # # include/sound/emu10k1.h # 2005/03/01 01:17:25+01:00 perex@suse.cz +2 -2 # [ALSA] Fix the Audigy SPDIF sample rate register definitions # # D:2005/03/01 08:17:25 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.57->1.58 # L: # Signed-off-by: Lee Revell # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 15:00:33+01:00 perex@suse.cz # [ALSA] remove _snd_rawmidi_runtime.trigger # # RawMidi Midlevel # Remove the trigger field from _snd_rawmidi_runtime because # it is never ever read. (This may be why nobody noticed that # snd_rawmidi_transmit_empty sets it to the wrong value.) # # Signed-off-by: Clemens Ladisch # # sound/core/rawmidi.c # 2005/02/28 01:54:40+01:00 perex@suse.cz +0 -11 # [ALSA] remove _snd_rawmidi_runtime.trigger # # D:2005/02/28 08:54:40 # C:RawMidi Midlevel # F:core/rawmidi.c:1.57->1.58 # F:include/rawmidi.h:1.12->1.13 # L:Remove the trigger field from _snd_rawmidi_runtime because # L:it is never ever read. (This may be why nobody noticed that # L:snd_rawmidi_transmit_empty sets it to the wrong value.) # Signed-off-by: Clemens Ladisch # # include/sound/rawmidi.h # 2005/02/28 01:54:40+01:00 perex@suse.cz +1 -2 # [ALSA] remove _snd_rawmidi_runtime.trigger # # D:2005/02/28 08:54:40 # C:RawMidi Midlevel # F:core/rawmidi.c:1.57->1.58 # F:include/rawmidi.h:1.12->1.13 # L:Remove the trigger field from _snd_rawmidi_runtime because # L:it is never ever read. (This may be why nobody noticed that # L:snd_rawmidi_transmit_empty sets it to the wrong value.) # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:59:45+01:00 perex@suse.cz # [ALSA] remove unsafe usage of urb->status # # USB generic driver # Remove unprotected accesses to urb->status and # substream->runtimer->trigger. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/28 01:50:18+01:00 perex@suse.cz +15 -4 # [ALSA] remove unsafe usage of urb->status # # D:2005/02/28 08:50:18 # C:USB generic driver # F:usb/usbmidi.c:1.43->1.44 # L:Remove unprotected accesses to urb->status and # L:substream->runtimer->trigger. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:58:55+01:00 perex@suse.cz # [ALSA] add port names for serial MIDI ports # # Generic drivers # Give each of the MIDI ports created by snd-serial-u16550 # a unique name. # # Signed-off-by: Clemens Ladisch # # sound/drivers/serial-u16550.c # 2005/02/28 01:46:30+01:00 perex@suse.cz +14 -2 # [ALSA] add port names for serial MIDI ports # # D:2005/02/28 08:46:30 # C:Generic drivers # F:drivers/serial-u16550.c:1.31->1.32 # L:Give each of the MIDI ports created by snd-serial-u16550 # L:a unique name. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:58:06+01:00 perex@suse.cz # [ALSA] fix counting of MIDI input overruns # # RawMidi Midlevel # Do not throw away the old value of the overrun counter when # more than one byte is received. # # Signed-off-by: Clemens Ladisch # # sound/core/rawmidi.c # 2005/02/28 01:44:40+01:00 perex@suse.cz +1 -1 # [ALSA] fix counting of MIDI input overruns # # D:2005/02/28 08:44:40 # C:RawMidi Midlevel # F:core/rawmidi.c:1.56->1.57 # L:Do not throw away the old value of the overrun counter when # L:more than one byte is received. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:57:19+01:00 perex@suse.cz # [ALSA] fix buffer wrap in snd_rawmidi_transmit_peek # # RawMidi Midlevel # Fix the behaviour and return value of snd_rawmidi_transmit_peek # when the buffer wraps around. # # Signed-off-by: Clemens Ladisch # # sound/core/rawmidi.c # 2005/02/28 01:42:25+01:00 perex@suse.cz +5 -1 # [ALSA] fix buffer wrap in snd_rawmidi_transmit_peek # # D:2005/02/28 08:42:25 # C:RawMidi Midlevel # F:core/rawmidi.c:1.55->1.56 # L:Fix the behaviour and return value of snd_rawmidi_transmit_peek # L:when the buffer wraps around. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:56:32+01:00 perex@suse.cz # [ALSA] add more USB MIDI quirks # # USB generic driver # Add support for Roland RS-70, SP-606, BOSS DR-880 # # Signed-off-by: Clemens Ladisch # # sound/usb/usbquirks.h # 2005/02/25 00:56:05+01:00 perex@suse.cz +39 -0 # [ALSA] add more USB MIDI quirks # # D:2005/02/25 07:56:05 # C:USB generic driver # F:usb/usbquirks.h:1.43->1.44 # L:Add support for Roland RS-70, SP-606, BOSS DR-880 # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:55:41+01:00 perex@suse.cz # [ALSA] AC97 quirk for Dell Precision 650 # # Intel8x0 driver # Added the ac97 quirk entry for Dell Precision 650. # # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0.c # 2005/02/24 04:55:36+01:00 perex@suse.cz +6 -0 # [ALSA] AC97 quirk for Dell Precision 650 # # D:2005/02/24 11:55:36 # C:Intel8x0 driver # F:pci/intel8x0.c:1.195->1.196 # L:Added the ac97 quirk entry for Dell Precision 650. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:54:56+01:00 perex@suse.cz # [ALSA] Add mixer controls to intel8x0m # # Intel8x0-modem driver # This patch adds a mixer switch to the intel8x0m driver, so that the # hook state can be controlled from userspace, instead of bringing the # line off hook on capture start. Please someone test, and merge into # cvs. Comments are welcome. # # Signed-off-by: Jaime A. Lopez Sollano # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0m.c # 2005/02/24 03:12:31+01:00 perex@suse.cz +59 -7 # [ALSA] Add mixer controls to intel8x0m # # D:2005/02/24 10:12:31 # C:Intel8x0-modem driver # F:pci/intel8x0m.c:1.28->1.29 # L:This patch adds a mixer switch to the intel8x0m driver, so that the # L:hook state can be controlled from userspace, instead of bringing the # L:line off hook on capture start. Please someone test, and merge into # L:cvs. Comments are welcome. # Signed-off-by: Jaime A. Lopez Sollano # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:54:11+01:00 perex@suse.cz # [ALSA] Fix CM9761 again # # AC97 Codec # Fixed the silent output playback problem on CM9761. # The SPDIF_CTRL register (0x6c) bit 17 was the culprit. # # The master volume is back again since it seems to have some # influence on the looped input sounds. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.c # 2005/02/23 07:04:02+01:00 perex@suse.cz +10 -6 # [ALSA] Fix CM9761 again # # D:2005/02/23 14:04:02 # C:AC97 Codec # F:pci/ac97/ac97_patch.c:1.74->1.75 # L:Fixed the silent output playback problem on CM9761. # L:The SPDIF_CTRL register (0x6c) bit 17 was the culprit. # L: # L:The master volume is back again since it seems to have some # L:influence on the looped input sounds. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:53:21+01:00 perex@suse.cz # [ALSA] do codec init more like windows does # # au88x0 driver # The following patch makes the codec init code act more like the windows # code. # # Signed-off-by: Jeff Muizelaar # Signed-off-by: Takashi Iwai # # sound/pci/au88x0/au88x0_core.c # 2005/02/23 04:00:31+01:00 perex@suse.cz +3 -2 # [ALSA] do codec init more like windows does # # D:2005/02/23 11:00:31 # C:au88x0 driver # F:pci/au88x0/au88x0_core.c:1.10->1.11 # L:The following patch makes the codec init code act more like the windows # L:code. # Signed-off-by: Jeff Muizelaar # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:52:35+01:00 perex@suse.cz # [ALSA] add Roland FANTOM-X support # # USB generic driver # This adds a USB MIDI quirk for the Roland FANTOM-X. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbquirks.h # 2005/02/23 01:04:57+01:00 perex@suse.cz +26 -13 # [ALSA] add Roland FANTOM-X support # # D:2005/02/23 08:04:57 # C:USB generic driver # F:usb/usbquirks.h:1.42->1.43 # L:This adds a USB MIDI quirk for the Roland FANTOM-X. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:51:49+01:00 perex@suse.cz # [ALSA] Add module_init and module_exit entries # # ALSA sequencer # From Mikael Magnusson : # Added the missing module_init and module_exit entries. # # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_midi_event.c # 2005/02/22 14:02:02+01:00 perex@suse.cz +12 -0 # [ALSA] Add module_init and module_exit entries # # D:2005/02/22 21:02:02 # C:ALSA sequencer # F:core/seq/seq_midi_event.c:1.14->1.15 # L:From Mikael Magnusson : # L:Added the missing module_init and module_exit entries. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:50:58+01:00 perex@suse.cz # [ALSA] Don't query chip models on CMI8338 # # CMIPCI driver # Don't call query_chip() for CMI8338. It's for CMI8738/8768 only. # # Signed-off-by: Takashi Iwai # # sound/pci/cmipci.c # 2005/02/22 13:18:21+01:00 perex@suse.cz +9 -8 # [ALSA] Don't query chip models on CMI8338 # # D:2005/02/22 20:18:21 # C:CMIPCI driver # F:pci/cmipci.c:1.79->1.80 # L:Don't call query_chip() for CMI8338. It's for CMI8738/8768 only. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:50:13+01:00 perex@suse.cz # [ALSA] Fix digital input # # HDA Codec driver # Fixed SPDIF digital input. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_cmedia.c # 2005/02/22 10:53:32+01:00 perex@suse.cz +8 -2 # [ALSA] Fix digital input # # D:2005/02/22 17:53:32 # C:HDA Codec driver # F:pci/hda/patch_cmedia.c:1.2->1.3 # L:Fixed SPDIF digital input. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:49:25+01:00 perex@suse.cz # [ALSA] ALC882 support, fix ALC880 5-stack mode # # HDA Codec driver # - Added the ALC882 support. # Currently no model selections; full-mode with digital I/O only. # - Fixed the widget assignment in ALC880 5-stack mode. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_realtek.c # 2005/02/22 10:50:53+01:00 perex@suse.cz +317 -14 # [ALSA] ALC882 support, fix ALC880 5-stack mode # # D:2005/02/22 17:50:53 # C:HDA Codec driver # F:pci/hda/patch_realtek.c:1.3->1.4 # L:- Added the ALC882 support. # L: Currently no model selections; full-mode with digital I/O only. # L:- Fixed the widget assignment in ALC880 5-stack mode. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:48:40+01:00 perex@suse.cz # [ALSA] CMI8768 patch # # CMIPCI driver # Hi, # # I made a patch for CM8768, which has the same PCI ID but there are # several HW diffecece, aas listed: # # 1. 8768 has no PCM volume control. # 2. The ADC of 8768 can only record in 44.1kHz or 48kHz. # 3. 8768 can support up to 8 channels. # # I made change for item 2 and 3, I want to use the softvol plugin but # don't know how to. The driver just don't generate the PCM volume slider # for now. # # Signed-off-by: ChenLi Tien # Signed-off-by: Takashi Iwai # # sound/pci/cmipci.c # 2005/02/22 10:29:37+01:00 perex@suse.cz +52 -11 # [ALSA] CMI8768 patch # # D:2005/02/22 17:29:37 # C:CMIPCI driver # F:pci/cmipci.c:1.78->1.79 # L:Hi, # L: # L:I made a patch for CM8768, which has the same PCI ID but there are # L:several HW diffecece, aas listed: # L: # L:1. 8768 has no PCM volume control. # L:2. The ADC of 8768 can only record in 44.1kHz or 48kHz. # L:3. 8768 can support up to 8 channels. # L: # L:I made change for item 2 and 3, I want to use the softvol plugin but # L:don't know how to. The driver just don't generate the PCM volume slider # L: for now. # Signed-off-by: ChenLi Tien # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:47:54+01:00 perex@suse.cz # [ALSA] Fix Digital Input # # HDA Codec driver,HDA generic driver # Fixed the SPDIF digital input support for HDA codecs. # New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default' # are added. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_local.h # 2005/02/22 10:18:08+01:00 perex@suse.cz +2 -0 # [ALSA] Fix Digital Input # # D:2005/02/22 17:17:57 # C:HDA Codec driver,HDA generic driver # F:pci/hda/hda_codec.c:1.5->1.6 # F:pci/hda/hda_codec.h:1.3->1.4 # F:pci/hda/hda_local.h:1.2->1.3 # L:Fixed the SPDIF digital input support for HDA codecs. # L:New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default' # L:are added. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.h # 2005/02/22 10:17:58+01:00 perex@suse.cz +1 -0 # [ALSA] Fix Digital Input # # D:2005/02/22 17:17:57 # C:HDA Codec driver,HDA generic driver # F:pci/hda/hda_codec.c:1.5->1.6 # F:pci/hda/hda_codec.h:1.3->1.4 # F:pci/hda/hda_local.h:1.2->1.3 # L:Fixed the SPDIF digital input support for HDA codecs. # L:New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default' # L:are added. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.c # 2005/02/22 10:17:57+01:00 perex@suse.cz +103 -2 # [ALSA] Fix Digital Input # # D:2005/02/22 17:17:57 # C:HDA Codec driver,HDA generic driver # F:pci/hda/hda_codec.c:1.5->1.6 # F:pci/hda/hda_codec.h:1.3->1.4 # F:pci/hda/hda_local.h:1.2->1.3 # L:Fixed the SPDIF digital input support for HDA codecs. # L:New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default' # L:are added. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:47:08+01:00 perex@suse.cz # [ALSA] fix Emagic broadcast port names # # USB generic driver # Name the broadcast port 'Broadcast' instead of 'Broadcast/Control' # because control messages are returned through the first MIDI port. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/22 00:36:12+01:00 perex@suse.cz +3 -3 # [ALSA] fix Emagic broadcast port names # # D:2005/02/22 07:36:12 # C:USB generic driver # F:usb/usbmidi.c:1.42->1.43 # L:Name the broadcast port 'Broadcast' instead of 'Broadcast/Control' # L:because control messages are returned through the first MIDI port. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:46:23+01:00 perex@suse.cz # [ALSA] ignore Emagic padding bytes # # USB generic driver # Ignore the 0xff padding bytes added by Emagic devices at the end # of input packets. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/22 00:34:39+01:00 perex@suse.cz +4 -0 # [ALSA] ignore Emagic padding bytes # # D:2005/02/22 07:34:39 # C:USB generic driver # F:usb/usbmidi.c:1.41->1.42 # L:Ignore the 0xff padding bytes added by Emagic devices at the end # L:of input packets. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:45:33+01:00 perex@suse.cz # [ALSA] add logging to send_bulk_static_data # # USB generic driver # Add the optional dump_urb call to send_bulk_static_data, too. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/22 00:33:22+01:00 perex@suse.cz +1 -0 # [ALSA] add logging to send_bulk_static_data # # D:2005/02/22 07:33:22 # C:USB generic driver # F:usb/usbmidi.c:1.40->1.41 # L:Add the optional dump_urb call to send_bulk_static_data, too. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:44:45+01:00 perex@suse.cz # [ALSA] add support for Emagic USB MIDI interfaces # # USB generic driver # Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx' # port switching) and for Unitor8/AMT8/MT4 devices. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbquirks.h # 2005/02/21 01:41:06+01:00 perex@suse.cz +41 -0 # [ALSA] add support for Emagic USB MIDI interfaces # # D:2005/02/21 08:41:06 # C:USB generic driver # F:usb/usbaudio.c:1.116->1.117 # F:usb/usbaudio.h:1.37->1.38 # F:usb/usbmidi.c:1.39->1.40 # F:usb/usbquirks.h:1.41->1.42 # L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx' # L:port switching) and for Unitor8/AMT8/MT4 devices. # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/21 01:41:06+01:00 perex@suse.cz +161 -1 # [ALSA] add support for Emagic USB MIDI interfaces # # D:2005/02/21 08:41:06 # C:USB generic driver # F:usb/usbaudio.c:1.116->1.117 # F:usb/usbaudio.h:1.37->1.38 # F:usb/usbmidi.c:1.39->1.40 # F:usb/usbquirks.h:1.41->1.42 # L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx' # L:port switching) and for Unitor8/AMT8/MT4 devices. # Signed-off-by: Clemens Ladisch # # sound/usb/usbaudio.h # 2005/02/21 01:41:06+01:00 perex@suse.cz +4 -0 # [ALSA] add support for Emagic USB MIDI interfaces # # D:2005/02/21 08:41:06 # C:USB generic driver # F:usb/usbaudio.c:1.116->1.117 # F:usb/usbaudio.h:1.37->1.38 # F:usb/usbmidi.c:1.39->1.40 # F:usb/usbquirks.h:1.41->1.42 # L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx' # L:port switching) and for Unitor8/AMT8/MT4 devices. # Signed-off-by: Clemens Ladisch # # sound/usb/usbaudio.c # 2005/02/21 01:41:06+01:00 perex@suse.cz +1 -0 # [ALSA] add support for Emagic USB MIDI interfaces # # D:2005/02/21 08:41:06 # C:USB generic driver # F:usb/usbaudio.c:1.116->1.117 # F:usb/usbaudio.h:1.37->1.38 # F:usb/usbmidi.c:1.39->1.40 # F:usb/usbquirks.h:1.41->1.42 # L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx' # L:port switching) and for Unitor8/AMT8/MT4 devices. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:43:50+01:00 perex@suse.cz # [ALSA] fix indentation # # Generic drivers # # # Signed-off-by: Clemens Ladisch # # sound/drivers/serial-u16550.c # 2005/02/21 01:17:50+01:00 perex@suse.cz +1 -1 # [ALSA] fix indentation # # D:2005/02/21 08:17:50 # C:Generic drivers # F:drivers/serial-u16550.c:1.30->1.31 # L: # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:43:04+01:00 perex@suse.cz # [ALSA] remove superfluous from_timer_port parameter # # ALSA sequencer # Removed superfluous from_timer_port parameter from # snd_seq_queue_process_event and queue_broadcast_event # functions. # # Signed-off-by: Clemens Ladisch # # sound/core/seq/seq_queue.h # 2005/02/21 01:17:11+01:00 perex@suse.cz +1 -1 # [ALSA] remove superfluous from_timer_port parameter # # D:2005/02/21 08:17:11 # C:ALSA sequencer # F:core/seq/seq_queue.c:1.16->1.17 # F:core/seq/seq_queue.h:1.9->1.10 # L:Removed superfluous from_timer_port parameter from # L:snd_seq_queue_process_event and queue_broadcast_event # L:functions. # Signed-off-by: Clemens Ladisch # # sound/core/seq/seq_queue.c # 2005/02/21 01:17:11+01:00 perex@suse.cz +15 -17 # [ALSA] remove superfluous from_timer_port parameter # # D:2005/02/21 08:17:11 # C:ALSA sequencer # F:core/seq/seq_queue.c:1.16->1.17 # F:core/seq/seq_queue.h:1.9->1.10 # L:Removed superfluous from_timer_port parameter from # L:snd_seq_queue_process_event and queue_broadcast_event # L:functions. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:42:11+01:00 perex@suse.cz # [ALSA] Fix SPDIF output # # HDA Codec driver # Fixed SPDIF output (over multi-out). # # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.h # 2005/02/18 10:51:16+01:00 perex@suse.cz +2 -1 # [ALSA] Fix SPDIF output # # D:2005/02/18 17:51:16 # C:HDA Codec driver # F:pci/hda/hda_codec.c:1.4->1.5 # F:pci/hda/hda_codec.h:1.2->1.3 # L:Fixed SPDIF output (over multi-out). # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.c # 2005/02/18 10:51:16+01:00 perex@suse.cz +70 -53 # [ALSA] Fix SPDIF output # # D:2005/02/18 17:51:16 # C:HDA Codec driver # F:pci/hda/hda_codec.c:1.4->1.5 # F:pci/hda/hda_codec.h:1.2->1.3 # L:Fixed SPDIF output (over multi-out). # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:41:26+01:00 perex@suse.cz # [ALSA] Fix mono volume/mute controls # # HDA generic driver # Fixed mono volume/mute controls. They were handled as stereo mistakenly. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_local.h # 2005/02/18 07:27:06+01:00 perex@suse.cz +2 -2 # [ALSA] Fix mono volume/mute controls # # D:2005/02/18 14:27:06 # C:HDA generic driver # F:pci/hda/hda_local.h:1.1->1.2 # L:Fixed mono volume/mute controls. They were handled as stereo mistakenly. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:40:37+01:00 perex@suse.cz # [ALSA] Don't set up the front stream twice # # HDA Codec driver # Don't set up the front stream twice in the loop. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.c # 2005/02/18 07:25:55+01:00 perex@suse.cz +1 -1 # [ALSA] Don't set up the front stream twice # # D:2005/02/18 14:25:55 # C:HDA Codec driver # F:pci/hda/hda_codec.c:1.3->1.4 # L:Don't set up the front stream twice in the loop. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:39:47+01:00 perex@suse.cz # [ALSA] Fix compilation with compat support # # ALSA sequencer # Fix the compilation with 32bit compat support. # # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_clientmgr.c # 2005/02/18 07:24:34+01:00 perex@suse.cz +2 -2 # [ALSA] Fix compilation with compat support # # D:2005/02/18 14:24:34 # C:ALSA sequencer # F:core/seq/seq_clientmgr.c:1.43->1.44 # L:Fix the compilation with 32bit compat support. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:38:56+01:00 perex@suse.cz # [ALSA] remove an unnecessary printk # # EMU10K1/EMU10K2 driver # This patch removes an unnecessary printk accidentally left in the # multichannel patch. # # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/voice.c # 2005/02/18 03:21:10+01:00 perex@suse.cz +1 -3 # [ALSA] remove an unnecessary printk # # D:2005/02/18 10:21:10 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/voice.c:1.6->1.7 # L:This patch removes an unnecessary printk accidentally left in the # L:multichannel patch. # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:38:10+01:00 perex@suse.cz # [ALSA] Fix invalid use of readl/writel # # KORG1212 driver # Fixed the invalid use of readl/writel to normal pointers. # # Signed-off-by: Takashi Iwai # # sound/pci/korg1212/korg1212.c # 2005/02/17 07:55:59+01:00 perex@suse.cz +6 -6 # [ALSA] Fix invalid use of readl/writel # # D:2005/02/17 14:55:59 # C:KORG1212 driver # F:pci/korg1212/korg1212.c:1.54->1.55 # L:Fixed the invalid use of readl/writel to normal pointers. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:37:23+01:00 perex@suse.cz # [ALSA] [SPARSE] Use NULL instead of 0 # # HDA Codec driver # Use NULL for pointers instead of 0. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_realtek.c # 2005/02/17 07:55:26+01:00 perex@suse.cz +1 -1 # [ALSA] [SPARSE] Use NULL instead of 0 # # D:2005/02/17 14:55:26 # C:HDA Codec driver # F:pci/hda/patch_realtek.c:1.2->1.3 # L:Use NULL for pointers instead of 0. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:36:33+01:00 perex@suse.cz # [ALSA] [SPARSE] Add __user pointer casts # # Wavefront drivers # Added __user pointer casts to sys_*() arguments # # Signed-off-by: Takashi Iwai # # sound/isa/wavefront/wavefront_synth.c # 2005/02/17 07:54:12+01:00 perex@suse.cz +3 -3 # [ALSA] [SPARSE] Add __user pointer casts # # D:2005/02/17 14:54:12 # C:Wavefront drivers # F:isa/wavefront/wavefront_synth.c:1.24->1.25 # L:Added __user pointer casts to sys_*() arguments # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:34:50+01:00 perex@suse.cz # [ALSA] [SPARSE] Fix __user pointers # # EMU10K1/EMU10K2 driver # Fix the access to __user pointers in some places. # Added proper casts. # # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emufx.c # 2005/02/17 07:51:52+01:00 perex@suse.cz +38 -33 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:51:52 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emufx.c:1.68->1.69 # L:Fix the access to __user pointers in some places. # L:Added proper casts. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:34:07+01:00 perex@suse.cz # [ALSA] Fix comiple with old gcc # # EMU10K1/EMU10K2 driver # Fix compile with old gcc. # # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emupcm.c # 2005/02/17 07:49:50+01:00 perex@suse.cz +4 -3 # [ALSA] Fix comiple with old gcc # # D:2005/02/17 14:49:50 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emupcm.c:1.39->1.40 # L:Fix compile with old gcc. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:33:19+01:00 perex@suse.cz # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # ALI5451 driver,ICE1712 driver # Use unsigned int :1 bitfields. # # Signed-off-by: Takashi Iwai # # sound/pci/maestro3.c # 2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0m.c # 2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/ice1712.h # 2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # sound/pci/cmipci.c # 2005/02/17 07:48:07+01:00 perex@suse.cz +3 -3 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # sound/pci/ali5451/ali5451.c # 2005/02/17 07:48:07+01:00 perex@suse.cz +2 -2 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # include/sound/ymfpci.h # 2005/02/17 07:48:07+01:00 perex@suse.cz +4 -4 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # include/sound/trident.h # 2005/02/17 07:48:07+01:00 perex@suse.cz +3 -3 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # include/sound/mixer_oss.h # 2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # include/sound/gus.h # 2005/02/17 07:48:07+01:00 perex@suse.cz +2 -2 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # include/sound/emu10k1.h # 2005/02/17 07:48:07+01:00 perex@suse.cz +2 -2 # [ALSA] [SPARSE] Use unsigned int :1 bitfields # # D:2005/02/17 14:48:07 # C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver # C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver # C:ALI5451 driver,ICE1712 driver # F:include/emu10k1.h:1.56->1.57 # F:include/gus.h:1.11->1.12 # F:include/mixer_oss.h:1.8->1.9 # F:include/trident.h:1.21->1.22 # F:include/ymfpci.h:1.18->1.19 # F:pci/cmipci.c:1.77->1.78 # F:pci/intel8x0m.c:1.27->1.28 # F:pci/maestro3.c:1.70->1.71 # F:pci/ali5451/ali5451.c:1.61->1.62 # F:pci/ice1712/ice1712.h:1.28->1.29 # L:Use unsigned int :1 bitfields. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:32:38+01:00 perex@suse.cz # [ALSA] [SPARSE] Fix __user pointers # # PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # Fixed __user pointers including other misc fixes: # - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # - added the proper segment change before passing the kernel pointer # as the user pointer in PCM code. # # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_memory.c # 2005/02/17 07:45:48+01:00 perex@suse.cz +4 -4 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:45:47 # C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # F:core/pcm_native.c:1.114->1.115 # F:core/rawmidi.c:1.54->1.55 # F:core/oss/pcm_oss.c:1.84->1.85 # F:core/seq/seq_clientmgr.c:1.42->1.43 # F:core/seq/seq_instr.c:1.12->1.13 # F:core/seq/seq_memory.c:1.19->1.20 # L:Fixed __user pointers including other misc fixes: # L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # L: - added the proper segment change before passing the kernel pointer # L: as the user pointer in PCM code. # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_instr.c # 2005/02/17 07:45:48+01:00 perex@suse.cz +3 -3 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:45:47 # C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # F:core/pcm_native.c:1.114->1.115 # F:core/rawmidi.c:1.54->1.55 # F:core/oss/pcm_oss.c:1.84->1.85 # F:core/seq/seq_clientmgr.c:1.42->1.43 # F:core/seq/seq_instr.c:1.12->1.13 # F:core/seq/seq_memory.c:1.19->1.20 # L:Fixed __user pointers including other misc fixes: # L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # L: - added the proper segment change before passing the kernel pointer # L: as the user pointer in PCM code. # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_clientmgr.c # 2005/02/17 07:45:47+01:00 perex@suse.cz +3 -3 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:45:47 # C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # F:core/pcm_native.c:1.114->1.115 # F:core/rawmidi.c:1.54->1.55 # F:core/oss/pcm_oss.c:1.84->1.85 # F:core/seq/seq_clientmgr.c:1.42->1.43 # F:core/seq/seq_instr.c:1.12->1.13 # F:core/seq/seq_memory.c:1.19->1.20 # L:Fixed __user pointers including other misc fixes: # L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # L: - added the proper segment change before passing the kernel pointer # L: as the user pointer in PCM code. # Signed-off-by: Takashi Iwai # # sound/core/rawmidi.c # 2005/02/17 07:45:47+01:00 perex@suse.cz +6 -4 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:45:47 # C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # F:core/pcm_native.c:1.114->1.115 # F:core/rawmidi.c:1.54->1.55 # F:core/oss/pcm_oss.c:1.84->1.85 # F:core/seq/seq_clientmgr.c:1.42->1.43 # F:core/seq/seq_instr.c:1.12->1.13 # F:core/seq/seq_memory.c:1.19->1.20 # L:Fixed __user pointers including other misc fixes: # L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # L: - added the proper segment change before passing the kernel pointer # L: as the user pointer in PCM code. # Signed-off-by: Takashi Iwai # # sound/core/pcm_native.c # 2005/02/17 07:45:47+01:00 perex@suse.cz +2 -2 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:45:47 # C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # F:core/pcm_native.c:1.114->1.115 # F:core/rawmidi.c:1.54->1.55 # F:core/oss/pcm_oss.c:1.84->1.85 # F:core/seq/seq_clientmgr.c:1.42->1.43 # F:core/seq/seq_instr.c:1.12->1.13 # F:core/seq/seq_memory.c:1.19->1.20 # L:Fixed __user pointers including other misc fixes: # L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # L: - added the proper segment change before passing the kernel pointer # L: as the user pointer in PCM code. # Signed-off-by: Takashi Iwai # # sound/core/oss/pcm_oss.c # 2005/02/17 07:45:47+01:00 perex@suse.cz +15 -12 # [ALSA] [SPARSE] Fix __user pointers # # D:2005/02/17 14:45:47 # C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer # F:core/pcm_native.c:1.114->1.115 # F:core/rawmidi.c:1.54->1.55 # F:core/oss/pcm_oss.c:1.84->1.85 # F:core/seq/seq_clientmgr.c:1.42->1.43 # F:core/seq/seq_instr.c:1.12->1.13 # F:core/seq/seq_memory.c:1.19->1.20 # L:Fixed __user pointers including other misc fixes: # L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL. # L: - added the proper segment change before passing the kernel pointer # L: as the user pointer in PCM code. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:31:51+01:00 perex@suse.cz # [ALSA] Fix the wrong function call from ioctl # # Control Midlevel # Fixed the call of a wrong function from ioctl. # # Signed-off-by: Takashi Iwai # # sound/core/control.c # 2005/02/17 07:40:34+01:00 perex@suse.cz +1 -1 # [ALSA] Fix the wrong function call from ioctl # # D:2005/02/17 14:40:34 # C:Control Midlevel # F:core/control.c:1.57->1.58 # L:Fixed the call of a wrong function from ioctl. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:31:07+01:00 perex@suse.cz # [ALSA] use unsigned 1-bit fields # # Virtual Midi # Can't have a boolean and a sign bit in 1 bit. # # Fix (14) boolean/bitfield sparse warning: # include/sound/seq_virmidi.h:41:16: warning: dubious one-bit signed bitfield # # Signed-off-by: Randy Dunlap # Signed-off-by: Takashi Iwai # # include/sound/seq_virmidi.h # 2005/02/17 04:55:52+01:00 perex@suse.cz +1 -1 # [ALSA] use unsigned 1-bit fields # # D:2005/02/17 11:55:52 # C:Virtual Midi # F:include/seq_virmidi.h:1.4->1.5 # L:Can't have a boolean and a sign bit in 1 bit. # L: # L:Fix (14) boolean/bitfield sparse warning: # L:include/sound/seq_virmidi.h:41:16: warning: dubious one-bit signed bitfield # Signed-off-by: Randy Dunlap # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:30:15+01:00 perex@suse.cz # [ALSA] Fix CM9761 again # # AC97 Codec # Revert the last addition for CM9761A support. The codec doesn't # support the real control of Master/PCM volumes, too. # Instead, fixed the default multi-channel register setting now. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.h # 2005/02/16 11:27:19+01:00 perex@suse.cz +0 -1 # [ALSA] Fix CM9761 again # # D:2005/02/16 18:27:12 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.171->1.172 # F:pci/ac97/ac97_patch.c:1.73->1.74 # F:pci/ac97/ac97_patch.h:1.18->1.19 # L:Revert the last addition for CM9761A support. The codec doesn't # L:support the real control of Master/PCM volumes, too. # L:Instead, fixed the default multi-channel register setting now. # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.c # 2005/02/16 11:27:17+01:00 perex@suse.cz +0 -26 # [ALSA] Fix CM9761 again # # D:2005/02/16 18:27:12 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.171->1.172 # F:pci/ac97/ac97_patch.c:1.73->1.74 # F:pci/ac97/ac97_patch.h:1.18->1.19 # L:Revert the last addition for CM9761A support. The codec doesn't # L:support the real control of Master/PCM volumes, too. # L:Instead, fixed the default multi-channel register setting now. # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_codec.c # 2005/02/16 11:27:12+01:00 perex@suse.cz +1 -2 # [ALSA] Fix CM9761 again # # D:2005/02/16 18:27:12 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.171->1.172 # F:pci/ac97/ac97_patch.c:1.73->1.74 # F:pci/ac97/ac97_patch.h:1.18->1.19 # L:Revert the last addition for CM9761A support. The codec doesn't # L:support the real control of Master/PCM volumes, too. # L:Instead, fixed the default multi-channel register setting now. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:29:36+01:00 perex@suse.cz # [ALSA] Fix CM9761A codec support # # AC97 Codec # Fixed the codec patch for (probably) CM9761A. It looks incompatible # with other CM9761 models. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.h # 2005/02/16 09:21:04+01:00 perex@suse.cz +1 -0 # [ALSA] Fix CM9761A codec support # # D:2005/02/16 16:21:03 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.170->1.171 # F:pci/ac97/ac97_patch.c:1.72->1.73 # F:pci/ac97/ac97_patch.h:1.17->1.18 # L:Fixed the codec patch for (probably) CM9761A. It looks incompatible # L:with other CM9761 models. # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.c # 2005/02/16 09:21:04+01:00 perex@suse.cz +28 -0 # [ALSA] Fix CM9761A codec support # # D:2005/02/16 16:21:03 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.170->1.171 # F:pci/ac97/ac97_patch.c:1.72->1.73 # F:pci/ac97/ac97_patch.h:1.17->1.18 # L:Fixed the codec patch for (probably) CM9761A. It looks incompatible # L:with other CM9761 models. # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_codec.c # 2005/02/16 09:21:03+01:00 perex@suse.cz +2 -1 # [ALSA] Fix CM9761A codec support # # D:2005/02/16 16:21:03 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.170->1.171 # F:pci/ac97/ac97_patch.c:1.72->1.73 # F:pci/ac97/ac97_patch.h:1.17->1.18 # L:Fixed the codec patch for (probably) CM9761A. It looks incompatible # L:with other CM9761 models. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:28:44+01:00 perex@suse.cz # [ALSA] add code to dump packets # # USB generic driver # add a compile-time option to log the contents of USB packets # # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/16 08:55:54+01:00 perex@suse.cz +22 -0 # [ALSA] add code to dump packets # # D:2005/02/16 15:55:54 # C:USB generic driver # F:usb/usbmidi.c:1.38->1.39 # L:add a compile-time option to log the contents of USB packets # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/03/02 14:28:03+01:00 perex@suse.cz # [ALSA] Fix detection of AFG node # # HDA Codec driver # Fix the detection of AFG node with unsolicited events. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.c # 2005/02/16 03:48:15+01:00 perex@suse.cz +2 -1 # [ALSA] Fix detection of AFG node # # D:2005/02/16 10:48:15 # C:HDA Codec driver # F:pci/hda/hda_codec.c:1.2->1.3 # L:Fix the detection of AFG node with unsolicited events. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/03/02 14:27:11+01:00 perex@suse.cz # [ALSA] emu10k1 - add 'voices' /proc entry for debugging the voice allocator # # EMU10K1/EMU10K2 driver # This patch adds a 'voices' /proc entry for debugging the voice # allocator. It also increases the size of the ptr_regs files to display # the values for all channels. Finally it updates the names of the EFX # recording inputs from '???' to 'FXBUS2_*'. # # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/emuproc.c # 2005/02/16 03:27:03+01:00 perex@suse.cz +61 -38 # [ALSA] emu10k1 - add 'voices' /proc entry for debugging the voice allocator # # D:2005/02/16 10:27:03 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emuproc.c:1.23->1.24 # L:This patch adds a 'voices' /proc entry for debugging the voice # L:allocator. It also increases the size of the ptr_regs files to display # L:the values for all channels. Finally it updates the names of the EFX # L:recording inputs from '???' to 'FXBUS2_*'. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 14:26:25+01:00 perex@suse.cz # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # EMU10K1/EMU10K2 driver # This series of patches adds a 16 channel non interleaved PCM playback # device, hw:x,3, to the emu10k1 driver. It also adds support for the # newly discovered per channel half loop interrupt. # # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/voice.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +70 -21 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/irq.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +15 -0 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/io.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +57 -0 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/emupcm.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +293 -21 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/emumixer.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +224 -1 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/emu10k1_callback.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +1 -1 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # sound/pci/emu10k1/emu10k1.c # 2005/02/16 03:25:36+01:00 perex@suse.cz +5 -0 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8] # # D:2005/02/16 10:25:36 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1.c:1.30->1.31 # F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 # F:pci/emu10k1/emumixer.c:1.29->1.30 # F:pci/emu10k1/emupcm.c:1.38->1.39 # F:pci/emu10k1/io.c:1.8->1.9 # F:pci/emu10k1/irq.c:1.11->1.12 # F:pci/emu10k1/voice.c:1.5->1.6 # L:This series of patches adds a 16 channel non interleaved PCM playback # L:device, hw:x,3, to the emu10k1 driver. It also adds support for the # L:newly discovered per channel half loop interrupt. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 14:25:34+01:00 perex@suse.cz # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [1/8] # # EMU10K1/EMU10K2 driver # Update header file for multichannel support. # Add some new register info. # # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # include/sound/emu10k1.h # 2005/02/16 03:19:02+01:00 perex@suse.cz +81 -12 # [ALSA] emu10k1 driver - add multichannel device hw:x,3 [1/8] # # D:2005/02/16 10:19:02 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.55->1.56 # L:Update header file for multichannel support. # L:Add some new register info. # Signed-Off-By: Lee Revell # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 14:24:49+01:00 perex@suse.cz # [ALSA] FM801 - radio: Fixed thinko for tea575x_tuner module parameter (int type not bool) # # FM801 driver # # # Signed-off-by: Jaroslav Kysela # # sound/pci/fm801.c # 2005/02/15 10:27:47+01:00 perex@suse.cz +1 -1 # [ALSA] FM801 - radio: Fixed thinko for tea575x_tuner module parameter (int type not bool) # # D:2005/02/15 17:27:47 # C:FM801 driver # F:pci/fm801.c:1.55->1.56 # L: # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 14:23:58+01:00 perex@suse.cz # [ALSA] TEA575x - add video release callback to avoid warning # # TEA575x tuner # # # Signed-off-by: Jaroslav Kysela # # sound/i2c/other/tea575x-tuner.c # 2005/02/15 03:23:46+01:00 perex@suse.cz +5 -0 # [ALSA] TEA575x - add video release callback to avoid warning # # D:2005/02/15 10:23:46 # C:TEA575x tuner # F:i2c/other/tea575x-tuner.c:1.3->1.4 # L: # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/03/02 11:17:39+01:00 perex@suse.cz # Alsa sync # # sound/pci/rme9652/hdsp.c # 2005/03/02 11:17:14+01:00 perex@suse.cz +0 -1 # ALSA sync # # sound/pci/intel8x0.c # 2005/03/02 11:17:13+01:00 perex@suse.cz +0 -16 # ALSA sync # # sound/pci/ac97/ac97_patch.c # 2005/03/02 09:51:31+01:00 perex@suse.cz +0 -24 # Auto merged # # BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8 # 2005/03/02 09:51:30+01:00 perex@suse.cz +0 -3 # Auto merged # # BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f # 2005/03/02 09:51:30+01:00 perex@suse.cz +0 -3 # Auto merged # # sound/pci/bt87x.c # 2005/03/02 09:51:30+01:00 perex@suse.cz +0 -1 # Auto merged # # sound/pci/atiixp.c # 2005/03/02 09:51:30+01:00 perex@suse.cz +0 -6 # Auto merged # # BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8 # 2005/03/02 09:51:30+01:00 perex@suse.cz +0 -0 # Merge rename: sound/core/ioctl32/pcm32.c -> BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8 # # BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f # 2005/03/02 09:51:30+01:00 perex@suse.cz +0 -0 # Merge rename: sound/core/ioctl32/ioctl32.c -> BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f # # ChangeSet # 2005/02/14 16:24:30+01:00 perex@suse.cz # [ALSA] Add ac97_quirk for Dell machine # # Intel8x0 driver # Added ac97_quirk option for Dell machine. # # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0.c # 2005/02/14 08:19:39+01:00 perex@suse.cz +6 -0 # [ALSA] Add ac97_quirk for Dell machine # # D:2005/02/14 15:19:39 # C:Intel8x0 driver # F:pci/intel8x0.c:1.194->1.195 # L:Added ac97_quirk option for Dell machine. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 16:23:16+01:00 perex@suse.cz # [ALSA] Enables SPDIF output on the Audigy2 Value # # EMU10K1/EMU10K2 driver # Enables SPDIF output on the Audigy2 Value. # It seems to work for PCM, but not AC3 yet. # # Signed-off-by: James Courtier-Dutton # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emu10k1_main.c # 2005/02/14 06:53:40+01:00 perex@suse.cz +9 -0 # [ALSA] Enables SPDIF output on the Audigy2 Value # # D:2005/02/14 13:53:40 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emu10k1_main.c:1.42->1.43 # L:Enables SPDIF output on the Audigy2 Value. # L:It seems to work for PCM, but not AC3 yet. # Signed-off-by: James Courtier-Dutton # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 16:22:05+01:00 perex@suse.cz # [ALSA] Add support for Audigy2LS on MSI motherboard # # CA0106 driver # Add support for Audigy2LS on MSI motherboard. # Fixes Bug #0901 # # Signed-off-by: James Courtier-Dutton # Signed-off-by: Takashi Iwai # # sound/pci/ca0106/ca0106_main.c # 2005/02/14 06:46:49+01:00 perex@suse.cz +10 -3 # [ALSA] Add support for Audigy2LS on MSI motherboard # # D:2005/02/14 13:46:49 # C:CA0106 driver # F:pci/ca0106/ca0106_main.c:1.3->1.4 # L:Add support for Audigy2LS on MSI motherboard. # L:Fixes Bug #0901 # Signed-off-by: James Courtier-Dutton # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 16:20:52+01:00 perex@suse.cz # [ALSA] fix typo in midi code # # RME HDSP driver # fix typo in midi code # # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # sound/pci/rme9652/hdsp.c # 2005/02/14 06:44:50+01:00 perex@suse.cz +1 -1 # [ALSA] fix typo in midi code # # D:2005/02/14 13:44:50 # C:RME HDSP driver # F:pci/rme9652/hdsp.c:1.82->1.83 # L:fix typo in midi code # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 16:19:39+01:00 perex@suse.cz # [ALSA] Fix rate setting on multiple codecs # # AC97 Codec # From Ron Cococcia : # # Fixed the PCM rate setting on multiple AC97 codecs. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_pcm.c # 2005/02/14 06:43:03+01:00 perex@suse.cz +3 -3 # [ALSA] Fix rate setting on multiple codecs # # D:2005/02/14 13:43:03 # C:AC97 Codec # F:pci/ac97/ac97_pcm.c:1.19->1.20 # L:From Ron Cococcia : # L: # L:Fixed the PCM rate setting on multiple AC97 codecs. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 16:18:30+01:00 perex@suse.cz # [ALSA] split snd_emu10k1_trigger_voice into trigger and prepare functions # # EMU10K1/EMU10K2 driver # This patch provides better sync between multiple voices by separating # the trigger_voice function into prepare_voice which sets up the volume # and filter parameters and trigger_voice which sets pitch target, current # and initial pitch and enables the voice interrupt. For standard PCM # this should not make much of a difference but will be important for # minimizing phase error between voices for multichannel PCM. # # This behavior was derived from the opensource.creative.com driver. # # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emupcm.c # 2005/02/14 06:37:23+01:00 perex@suse.cz +26 -8 # [ALSA] split snd_emu10k1_trigger_voice into trigger and prepare functions # # D:2005/02/14 13:37:23 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emupcm.c:1.37->1.38 # L:This patch provides better sync between multiple voices by separating # L:the trigger_voice function into prepare_voice which sets up the volume # L:and filter parameters and trigger_voice which sets pitch target, current # L:and initial pitch and enables the voice interrupt. For standard PCM # L:this should not make much of a difference but will be important for # L:minimizing phase error between voices for multichannel PCM. # L: # L:This behavior was derived from the opensource.creative.com driver. # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 16:03:46+01:00 perex@suse.cz # [ALSA] Remove unused yss225.h # # Wavefront drivers # yss225.h is just obsolete, not used/read by any codes. # Let's remove it. # # Signed-off-by: Takashi Iwai # # BitKeeper/deleted/.del-yss225.h~c73ea10a3054ca69 # 2005/02/14 16:03:14+01:00 perex@suse.cz +0 -0 # Delete: include/sound/yss225.h # # ChangeSet # 2005/02/14 15:31:18+01:00 perex@suse.cz # [ALSA] Added support for Terratec PHASE 22 # # ICE1712 driver,ICE1724 driver # I've struggled for a couple of days with Terratec Phase 22 card. # Chips used on it are well known but the combination is somehow unique. # Phase 88 should have been similar... but it actually uses 1712 # instead of 1721 (Envy24HT-S). So here is the patch against release # 1.0.8 that adds Phase 22 to ice1724. I've tested only analog part # (balances 1/4 TRS in and outs). # # Signed-off-by: Misha Zhilin # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/phase.h # 2005/02/14 14:19:10+01:00 perex@suse.cz +34 -0 # [ALSA] Added support for Terratec PHASE 22 # # D:2005/02/09 10:47:51 # C:ICE1712 driver,ICE1724 driver # F:pci/ice1712/Makefile:1.15->1.16 # F:pci/ice1712/ice1724.c:1.50->1.51 # F:pci/ice1712/phase.c:INITIAL->1.1 # F:pci/ice1712/phase.h:INITIAL->1.1 # L:I've struggled for a couple of days with Terratec Phase 22 card. # L:Chips used on it are well known but the combination is somehow unique. # L:Phase 88 should have been similar... but it actually uses 1712 # L:instead of 1721 (Envy24HT-S). So here is the patch against release # L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part # L:(balances 1/4 TRS in and outs). # Signed-off-by: Misha Zhilin # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/phase.h # 2005/02/14 14:19:10+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/phase.h # # sound/pci/ice1712/ice1724.c # 2005/02/09 03:47:51+01:00 perex@suse.cz +3 -0 # [ALSA] Added support for Terratec PHASE 22 # # D:2005/02/09 10:47:51 # C:ICE1712 driver,ICE1724 driver # F:pci/ice1712/Makefile:1.15->1.16 # F:pci/ice1712/ice1724.c:1.50->1.51 # F:pci/ice1712/phase.c:INITIAL->1.1 # F:pci/ice1712/phase.h:INITIAL->1.1 # L:I've struggled for a couple of days with Terratec Phase 22 card. # L:Chips used on it are well known but the combination is somehow unique. # L:Phase 88 should have been similar... but it actually uses 1712 # L:instead of 1721 (Envy24HT-S). So here is the patch against release # L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part # L:(balances 1/4 TRS in and outs). # Signed-off-by: Misha Zhilin # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/Makefile # 2005/02/09 03:47:51+01:00 perex@suse.cz +1 -1 # [ALSA] Added support for Terratec PHASE 22 # # D:2005/02/09 10:47:51 # C:ICE1712 driver,ICE1724 driver # F:pci/ice1712/Makefile:1.15->1.16 # F:pci/ice1712/ice1724.c:1.50->1.51 # F:pci/ice1712/phase.c:INITIAL->1.1 # F:pci/ice1712/phase.h:INITIAL->1.1 # L:I've struggled for a couple of days with Terratec Phase 22 card. # L:Chips used on it are well known but the combination is somehow unique. # L:Phase 88 should have been similar... but it actually uses 1712 # L:instead of 1721 (Envy24HT-S). So here is the patch against release # L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part # L:(balances 1/4 TRS in and outs). # Signed-off-by: Misha Zhilin # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/phase.c # 2005/02/14 14:19:06+01:00 perex@suse.cz +138 -0 # [ALSA] Added support for Terratec PHASE 22 # # D:2005/02/09 10:47:51 # C:ICE1712 driver,ICE1724 driver # F:pci/ice1712/Makefile:1.15->1.16 # F:pci/ice1712/ice1724.c:1.50->1.51 # F:pci/ice1712/phase.c:INITIAL->1.1 # F:pci/ice1712/phase.h:INITIAL->1.1 # L:I've struggled for a couple of days with Terratec Phase 22 card. # L:Chips used on it are well known but the combination is somehow unique. # L:Phase 88 should have been similar... but it actually uses 1712 # L:instead of 1721 (Envy24HT-S). So here is the patch against release # L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part # L:(balances 1/4 TRS in and outs). # Signed-off-by: Misha Zhilin # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/phase.c # 2005/02/14 14:19:06+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/phase.c # # ChangeSet # 2005/02/14 15:27:44+01:00 perex@suse.cz # [ALSA] AK4114 - fixed workqueue initialization & removed debug code # # AK4114 receiver # # # Signed-off-by: Jaroslav Kysela # # sound/i2c/other/ak4114.c # 2005/01/28 07:25:23+01:00 perex@suse.cz +7 -8 # [ALSA] AK4114 - fixed workqueue initialization & removed debug code # # D:2005/01/28 14:25:23 # C:AK4114 receiver # F:i2c/other/ak4114.c:1.2->1.3 # L: # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/02/14 15:26:34+01:00 perex@suse.cz # [ALSA] fix typo in assignment of snd_ak4114_spdif_playback_put # # AK4114 receiver # snd_ak4114_spdif_playback_put was assigned to the .get callback # which resulted in a duplicate initialization of that member # # Signed-off-by: Clemens Ladisch # # sound/i2c/other/ak4114.c # 2005/01/21 10:43:47+01:00 perex@suse.cz +1 -1 # [ALSA] fix typo in assignment of snd_ak4114_spdif_playback_put # # D:2005/01/21 17:43:47 # C:AK4114 receiver # F:i2c/other/ak4114.c:1.1->1.2 # L:snd_ak4114_spdif_playback_put was assigned to the .get callback # L:which resulted in a duplicate initialization of that member # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:25:22+01:00 perex@suse.cz # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # ICE1712 driver,ICE1724 driver # Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # also updated (cleanups and new callbacks). # # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/revo.c # 2005/01/18 08:48:02+01:00 perex@suse.cz +11 -0 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/prodigy192.c # 2005/01/18 08:48:01+01:00 perex@suse.cz +2 -2 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/juli.h # 2005/01/20 19:12:22+01:00 perex@suse.cz +10 -0 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/juli.c # 2005/01/20 19:12:18+01:00 perex@suse.cz +230 -0 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/ice1724.c # 2005/01/18 08:48:00+01:00 perex@suse.cz +42 -26 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/ice1712.h # 2005/01/18 08:48:00+01:00 perex@suse.cz +8 -1 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/ice1712.c # 2005/01/18 08:48:00+01:00 perex@suse.cz +18 -14 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/envy24ht.h # 2005/01/18 08:48:00+01:00 perex@suse.cz +1 -1 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/ak4xxx.c # 2005/01/18 08:48:00+01:00 perex@suse.cz +8 -4 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/Makefile # 2005/01/18 08:48:00+01:00 perex@suse.cz +1 -1 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/i2c/other/ak4xxx-adda.c # 2005/01/18 08:47:47+01:00 perex@suse.cz +33 -3 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/i2c/other/Makefile # 2005/01/18 08:47:47+01:00 perex@suse.cz +2 -0 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # include/sound/ak4xxx-adda.h # 2005/01/18 08:47:59+01:00 perex@suse.cz +2 -1 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # include/sound/ak4114.h # 2005/01/20 19:11:13+01:00 perex@suse.cz +205 -0 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # sound/pci/ice1712/juli.h # 2005/01/20 19:12:22+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/juli.h # # sound/pci/ice1712/juli.c # 2005/01/20 19:12:18+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/juli.c # # sound/i2c/other/ak4114.c # 2005/01/20 19:11:04+01:00 perex@suse.cz +581 -0 # [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358 # # D:2005/01/18 15:47:47 # C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters # C:ICE1712 driver,ICE1724 driver # F:i2c/other/Makefile:1.3->1.4 # F:i2c/other/ak4114.c:INITIAL->1.1 # F:i2c/other/ak4xxx-adda.c:1.8->1.9 # F:include/ak4114.h:INITIAL->1.1 # F:include/ak4xxx-adda.h:1.3->1.4 # F:pci/ice1712/Makefile:1.14->1.15 # F:pci/ice1712/ak4xxx.c:1.10->1.11 # F:pci/ice1712/envy24ht.h:1.4->1.5 # F:pci/ice1712/ice1712.c:1.64->1.65 # F:pci/ice1712/ice1712.h:1.27->1.28 # F:pci/ice1712/ice1724.c:1.49->1.50 # F:pci/ice1712/juli.c:INITIAL->1.1 # F:pci/ice1712/juli.h:INITIAL->1.1 # F:pci/ice1712/prodigy192.c:1.1->1.2 # F:pci/ice1712/revo.c:1.8->1.9 # L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114, # L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are # L:also updated (cleanups and new callbacks). # Signed-off-by: Jaroslav Kysela # # include/sound/ak4114.h # 2005/01/20 19:11:13+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/include/sound/ak4114.h # # sound/i2c/other/ak4114.c # 2005/01/20 19:11:04+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/i2c/other/ak4114.c # # ChangeSet # 2005/02/14 15:21:35+01:00 perex@suse.cz # [ALSA] add STAC9708 output bias mixer control # # AC97 Codec # This adds a mixer control for an undocumented bit of the STAC9708 # that somehow affects the analog output. This should help reducing # the distortion at high output levels on ymfpci and SBLive cards. # # Signed-off-by: Clemens Ladisch # # sound/pci/ac97/ac97_patch.c # 2005/02/11 02:56:09+01:00 perex@suse.cz +27 -0 # [ALSA] add STAC9708 output bias mixer control # # D:2005/02/11 09:56:09 # C:AC97 Codec # F:pci/ac97/ac97_patch.c:1.71->1.72 # L:This adds a mixer control for an undocumented bit of the STAC9708 # L:that somehow affects the analog output. This should help reducing # L:the distortion at high output levels on ymfpci and SBLive cards. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:20:21+01:00 perex@suse.cz # [ALSA] MPU-401 driver cleanup # # MPU401 UART # Correctly check for error codes returned by pnp_register_driver, # use a common function for registering the sound card, and remove # many #ifdef's. # # Signed-off-by: Matthieu Castet # Signed-off-by: Clemens Ladisch # # sound/drivers/mpu401/mpu401.c # 2005/02/11 02:51:56+01:00 perex@suse.cz +68 -74 # [ALSA] MPU-401 driver cleanup # # D:2005/02/11 09:51:56 # C:MPU401 UART # F:drivers/mpu401/mpu401.c:1.22->1.23 # L:Correctly check for error codes returned by pnp_register_driver, # L:use a common function for registering the sound card, and remove # L:many #ifdef's. # Signed-off-by: Matthieu Castet # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:19:12+01:00 perex@suse.cz # [ALSA] add 96Khz support and setting sample rate for direct SPDIF output # # EMU10K1/EMU10K2 driver # This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF # Bypass' (not P16V) playback mode available on the Audigy1 and 2 and # newer SBLives (?). It lets you bypass the 48khz DSP resampling when # using the card in digital mode. It also adds 96khz analog playback # support, good for testing but less interesting because it's downsampled # to 48khz. A new mixer control 'Audigy SPDIF Output Sample Rate' is # created, you can choose 44100, 48000, or 96000. Standard SPDIF # playback, AC3 passthrough (real 96khz playback), and analog playback # (96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz # wav file. Only the last was tested due to lack of any SPDIF hardware. # # This was derived mostly from the opensource.creative.com driver. All # that was needed for 96khz playback to work in analog mode was changing # the format to 8000_96000 (looks like the creative driver supports 192khz # too). And, of course this sample rate has always been supported (albeit # downsampled) because if you have 48khz samples in a soundfont the # envelope engine has to be able to pitch shift them in both directions. # # I still have not been able to figure out how to get 24 bit playback to # work. This is possible, independent of the P16V, for spdif and analog # 24/48 playback via the DSP. I do know how to access the full 24 bits # from the ADC from within the DSP, just not how to get it in there. For # one thing I have no idea which 24 bit format it supports. Some of them # seemed to work with JACK but produced noise. # # This was generated with my multichannel patch but it applies against # ALSA CVS as well. # # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emupcm.c # 2005/02/10 04:52:51+01:00 perex@suse.cz +2 -2 # [ALSA] add 96Khz support and setting sample rate for direct SPDIF output # # D:2005/02/10 11:52:50 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.54->1.55 # F:pci/emu10k1/emumixer.c:1.28->1.29 # F:pci/emu10k1/emupcm.c:1.36->1.37 # L:This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF # L:Bypass' (not P16V) playback mode available on the Audigy1 and 2 and # L:newer SBLives (?). It lets you bypass the 48khz DSP resampling when # L:using the card in digital mode. It also adds 96khz analog playback # L:support, good for testing but less interesting because it's downsampled # L:to 48khz. A new mixer control 'Audigy SPDIF Output Sample Rate' is # L:created, you can choose 44100, 48000, or 96000. Standard SPDIF # L:playback, AC3 passthrough (real 96khz playback), and analog playback # L:(96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz # L:wav file. Only the last was tested due to lack of any SPDIF hardware. # L: # L:This was derived mostly from the opensource.creative.com driver. All # L:that was needed for 96khz playback to work in analog mode was changing # L:the format to 8000_96000 (looks like the creative driver supports 192khz # L:too). And, of course this sample rate has always been supported (albeit # L:downsampled) because if you have 48khz samples in a soundfont the # L:envelope engine has to be able to pitch shift them in both directions. # L: # L:I still have not been able to figure out how to get 24 bit playback to # L:work. This is possible, independent of the P16V, for spdif and analog # L:24/48 playback via the DSP. I do know how to access the full 24 bits # L:from the ADC from within the DSP, just not how to get it in there. For # L:one thing I have no idea which 24 bit format it supports. Some of them # L:seemed to work with JACK but produced noise. # L: # L:This was generated with my multichannel patch but it applies against # L:ALSA CVS as well. # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emumixer.c # 2005/02/10 04:52:51+01:00 perex@suse.cz +89 -0 # [ALSA] add 96Khz support and setting sample rate for direct SPDIF output # # D:2005/02/10 11:52:50 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.54->1.55 # F:pci/emu10k1/emumixer.c:1.28->1.29 # F:pci/emu10k1/emupcm.c:1.36->1.37 # L:This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF # L:Bypass' (not P16V) playback mode available on the Audigy1 and 2 and # L:newer SBLives (?). It lets you bypass the 48khz DSP resampling when # L:using the card in digital mode. It also adds 96khz analog playback # L:support, good for testing but less interesting because it's downsampled # L:to 48khz. A new mixer control 'Audigy SPDIF Output Sample Rate' is # L:created, you can choose 44100, 48000, or 96000. Standard SPDIF # L:playback, AC3 passthrough (real 96khz playback), and analog playback # L:(96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz # L:wav file. Only the last was tested due to lack of any SPDIF hardware. # L: # L:This was derived mostly from the opensource.creative.com driver. All # L:that was needed for 96khz playback to work in analog mode was changing # L:the format to 8000_96000 (looks like the creative driver supports 192khz # L:too). And, of course this sample rate has always been supported (albeit # L:downsampled) because if you have 48khz samples in a soundfont the # L:envelope engine has to be able to pitch shift them in both directions. # L: # L:I still have not been able to figure out how to get 24 bit playback to # L:work. This is possible, independent of the P16V, for spdif and analog # L:24/48 playback via the DSP. I do know how to access the full 24 bits # L:from the ADC from within the DSP, just not how to get it in there. For # L:one thing I have no idea which 24 bit format it supports. Some of them # L:seemed to work with JACK but produced noise. # L: # L:This was generated with my multichannel patch but it applies against # L:ALSA CVS as well. # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # include/sound/emu10k1.h # 2005/02/10 04:52:50+01:00 perex@suse.cz +4 -3 # [ALSA] add 96Khz support and setting sample rate for direct SPDIF output # # D:2005/02/10 11:52:50 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.54->1.55 # F:pci/emu10k1/emumixer.c:1.28->1.29 # F:pci/emu10k1/emupcm.c:1.36->1.37 # L:This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF # L:Bypass' (not P16V) playback mode available on the Audigy1 and 2 and # L:newer SBLives (?). It lets you bypass the 48khz DSP resampling when # L:using the card in digital mode. It also adds 96khz analog playback # L:support, good for testing but less interesting because it's downsampled # L:to 48khz. A new mixer control 'Audigy SPDIF Output Sample Rate' is # L:created, you can choose 44100, 48000, or 96000. Standard SPDIF # L:playback, AC3 passthrough (real 96khz playback), and analog playback # L:(96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz # L:wav file. Only the last was tested due to lack of any SPDIF hardware. # L: # L:This was derived mostly from the opensource.creative.com driver. All # L:that was needed for 96khz playback to work in analog mode was changing # L:the format to 8000_96000 (looks like the creative driver supports 192khz # L:too). And, of course this sample rate has always been supported (albeit # L:downsampled) because if you have 48khz samples in a soundfont the # L:envelope engine has to be able to pitch shift them in both directions. # L: # L:I still have not been able to figure out how to get 24 bit playback to # L:work. This is possible, independent of the P16V, for spdif and analog # L:24/48 playback via the DSP. I do know how to access the full 24 bits # L:from the ADC from within the DSP, just not how to get it in there. For # L:one thing I have no idea which 24 bit format it supports. Some of them # L:seemed to work with JACK but produced noise. # L: # L:This was generated with my multichannel patch but it applies against # L:ALSA CVS as well. # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:18:00+01:00 perex@suse.cz # [ALSA] fix sound/isa/gus/interwave.c compile with PNP=n # # AMD InterWave driver # Emmanuel Colbus sent this patch one month ago with the following # description: # # There is a trivial bug in the file sound/isa/gus/interwave.c . # The variable isapnp is defined only if CONFIG_PNP is enabled, but it is # always used few lines after. # # Signed-off-by: Adrian Bunk # Signed-off-by: Takashi Iwai # # sound/isa/gus/interwave.c # 2005/02/10 04:35:42+01:00 perex@suse.cz +2 -0 # [ALSA] fix sound/isa/gus/interwave.c compile with PNP=n # # D:2005/02/10 11:35:42 # C:AMD InterWave driver # F:isa/gus/interwave.c:1.37->1.38 # L:Emmanuel Colbus sent this patch one month ago with the following # L:description: # L: # L:There is a trivial bug in the file sound/isa/gus/interwave.c . # L:The variable isapnp is defined only if CONFIG_PNP is enabled, but it is # L:always used few lines after. # Signed-off-by: Adrian Bunk # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:11:49+01:00 perex@suse.cz # [ALSA] Bind master and HP controls with hp_only quirk # # AC97 Codec # Bind master and HP controls when hp_only quirk is given, instead # of removing master control. This fixes the problem of some laptops # which require sync'ed volume for PC-speaker and headphone output. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_codec.c # 2005/02/09 03:27:15+01:00 perex@suse.cz +30 -0 # [ALSA] Bind master and HP controls with hp_only quirk # # D:2005/02/09 10:27:15 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.169->1.170 # L:Bind master and HP controls when hp_only quirk is given, instead # L:of removing master control. This fixes the problem of some laptops # L:which require sync'ed volume for PC-speaker and headphone output. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:10:40+01:00 perex@suse.cz # [ALSA] fixes als100 not detecting opl3 # # ALS100 driver # This patch fixes issue when opl3 device couldn't be found # due to numbering of devices in pnp card, because search of # opl3 device started from mpu device, which could have number # greater than opl3 could. # # Example: # MPU is 00:01.03 # and # OPL is 00:01.01 # # Signed-off-by: Anton Romanov # Signed-off-by: Clemens Ladisch # # sound/isa/als100.c # 2005/02/07 08:20:21+01:00 perex@suse.cz +1 -1 # [ALSA] fixes als100 not detecting opl3 # # D:2005/02/07 15:20:21 # C:ALS100 driver # F:isa/als100.c:1.29->1.30 # L:This patch fixes issue when opl3 device couldn't be found # L:due to numbering of devices in pnp card, because search of # L:opl3 device started from mpu device, which could have number # L:greater than opl3 could. # L: # L:Example: # L:MPU is 00:01.03 # L:and # L:OPL is 00:01.01 # Signed-off-by: Anton Romanov # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:09:33+01:00 perex@suse.cz # [ALSA] enable disabling of isapnp # # OPL3SA2 driver # Fixed a logic error that prevented the 'isapnp=0' module # parameter from taking effect. # # Signed-off-by: Clemens Ladisch # # sound/isa/opl3sa2.c # 2005/02/07 02:05:26+01:00 perex@suse.cz +1 -1 # [ALSA] enable disabling of isapnp # # D:2005/02/07 09:05:26 # C:OPL3SA2 driver # F:isa/opl3sa2.c:1.43->1.44 # L:Fixed a logic error that prevented the 'isapnp=0' module # L:parameter from taking effect. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:08:24+01:00 perex@suse.cz # [ALSA] MPU-401 PnP support # # Documentation,MPU401 UART # Replace the ACPI PnP code with generic PnP calls. # # Signed-off-by: Clemens Ladisch # # sound/drivers/mpu401/mpu401.c # 2005/02/07 01:40:37+01:00 perex@suse.cz +73 -121 # [ALSA] MPU-401 PnP support # # D:2005/02/07 08:40:37 # C:Documentation,MPU401 UART # F:Documentation/ALSA-Configuration.txt:1.68->1.69 # F:drivers/mpu401/mpu401.c:1.21->1.22 # L:Replace the ACPI PnP code with generic PnP calls. # Signed-off-by: Clemens Ladisch # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/02/07 01:40:37+01:00 perex@suse.cz +2 -3 # [ALSA] MPU-401 PnP support # # D:2005/02/07 08:40:37 # C:Documentation,MPU401 UART # F:Documentation/ALSA-Configuration.txt:1.68->1.69 # F:drivers/mpu401/mpu401.c:1.21->1.22 # L:Replace the ACPI PnP code with generic PnP calls. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:07:15+01:00 perex@suse.cz # [ALSA] Add quirk for Fujitsu S6210 # # Intel8x0 driver # Added ac97_quirk for Fujitsu S6210. # # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0.c # 2005/02/04 10:00:49+01:00 perex@suse.cz +6 -0 # [ALSA] Add quirk for Fujitsu S6210 # # D:2005/02/04 17:00:49 # C:Intel8x0 driver # F:pci/intel8x0.c:1.193->1.194 # L:Added ac97_quirk for Fujitsu S6210. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:06:09+01:00 perex@suse.cz # [ALSA] Add __iomem prefix # # BT87x driver # Added __iomem prefix to the mmio pointer. # # Signed-off-by: Takashi Iwai # # sound/pci/bt87x.c # 2005/02/04 09:08:58+01:00 perex@suse.cz +1 -1 # [ALSA] Add __iomem prefix # # D:2005/02/04 16:08:58 # C:BT87x driver # F:pci/bt87x.c:1.19->1.20 # L:Added __iomem prefix to the mmio pointer. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:04:59+01:00 perex@suse.cz # [ALSA] Remove interruptible_sleep_on_timeout(). # # ALSA<-OSS sequencer # Use wait_event_interruptible_timeout() instead of deprecated # interruptible_sleep_on_timeout(). # # Signed-off-by: Takashi Iwai # # sound/core/seq/oss/seq_oss_writeq.c # 2005/02/04 08:31:49+01:00 perex@suse.cz +5 -19 # [ALSA] Remove interruptible_sleep_on_timeout(). # # D:2005/02/04 15:31:49 # C:ALSA<-OSS sequencer # F:core/seq/oss/seq_oss_readq.c:1.11->1.12 # F:core/seq/oss/seq_oss_writeq.c:1.6->1.7 # L:Use wait_event_interruptible_timeout() instead of deprecated # L:interruptible_sleep_on_timeout(). # Signed-off-by: Takashi Iwai # # sound/core/seq/oss/seq_oss_readq.c # 2005/02/04 08:31:49+01:00 perex@suse.cz +4 -1 # [ALSA] Remove interruptible_sleep_on_timeout(). # # D:2005/02/04 15:31:49 # C:ALSA<-OSS sequencer # F:core/seq/oss/seq_oss_readq.c:1.11->1.12 # F:core/seq/oss/seq_oss_writeq.c:1.6->1.7 # L:Use wait_event_interruptible_timeout() instead of deprecated # L:interruptible_sleep_on_timeout(). # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:03:52+01:00 perex@suse.cz # [ALSA] remove interruptible_sleep_on_timeout() usage # # GUS Library # Replace deprecated interruptible_sleep_on_timeout() with # wait_event_timeout(). Code is not identical, as the current sleeping # system is 1 jiffy at a time checking atomic_read()'s return every # iteration. Patch is compile-tested. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/isa/gus/gus_pcm.c # 2005/02/04 08:30:35+01:00 perex@suse.cz +3 -9 # [ALSA] remove interruptible_sleep_on_timeout() usage # # D:2005/02/04 15:30:35 # C:GUS Library # F:isa/gus/gus_pcm.c:1.24->1.25 # L:Replace deprecated interruptible_sleep_on_timeout() with # L:wait_event_timeout(). Code is not identical, as the current sleeping # L:system is 1 jiffy at a time checking atomic_read()'s return every # L:iteration. Patch is compile-tested. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:02:40+01:00 perex@suse.cz # [ALSA] Korg1212 updates # # KORG1212 driver # This patches covers the following issues: # # - solves double 'spin_lock_irqsave' problems; # - eliminate the use of deprecated function 'sleep_on_timeout'; # - clarify some 'printk' messages; and # - logs korg DMA Errors due to PCI congestion. # # Signed-off-by: Haroldo Gamal # Signed-off-by: Takashi Iwai # # sound/pci/korg1212/korg1212.c # 2005/02/03 10:30:57+01:00 perex@suse.cz +43 -32 # [ALSA] Korg1212 updates # # D:2005/02/03 17:30:57 # C:KORG1212 driver # F:pci/korg1212/korg1212.c:1.53->1.54 # L:This patches covers the following issues: # L: # L: - solves double 'spin_lock_irqsave' problems; # L: - eliminate the use of deprecated function 'sleep_on_timeout'; # L: - clarify some 'printk' messages; and # L: - logs korg DMA Errors due to PCI congestion. # Signed-off-by: Haroldo Gamal # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 15:01:33+01:00 perex@suse.cz # [ALSA] Novation and MOTU USB MIDI support # # USB generic driver # Rewrote USB MIDI protocol handling code to use callbacks # for each protocol; # added support for Novation and MOTU protocols; # changed detection code to allow interrupt endpoints. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbquirks.h # 2005/02/02 05:54:08+01:00 perex@suse.cz +44 -6 # [ALSA] Novation and MOTU USB MIDI support # # D:2005/02/02 12:54:07 # C:USB generic driver # F:usb/usbaudio.c:1.115->1.116 # F:usb/usbaudio.h:1.36->1.37 # F:usb/usbmidi.c:1.37->1.38 # F:usb/usbquirks.h:1.40->1.41 # L:Rewrote USB MIDI protocol handling code to use callbacks # L:for each protocol; # L:added support for Novation and MOTU protocols; # L:changed detection code to allow interrupt endpoints. # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/02 05:54:08+01:00 perex@suse.cz +270 -174 # [ALSA] Novation and MOTU USB MIDI support # # D:2005/02/02 12:54:07 # C:USB generic driver # F:usb/usbaudio.c:1.115->1.116 # F:usb/usbaudio.h:1.36->1.37 # F:usb/usbmidi.c:1.37->1.38 # F:usb/usbquirks.h:1.40->1.41 # L:Rewrote USB MIDI protocol handling code to use callbacks # L:for each protocol; # L:added support for Novation and MOTU protocols; # L:changed detection code to allow interrupt endpoints. # Signed-off-by: Clemens Ladisch # # sound/usb/usbaudio.h # 2005/02/02 05:54:08+01:00 perex@suse.cz +9 -2 # [ALSA] Novation and MOTU USB MIDI support # # D:2005/02/02 12:54:07 # C:USB generic driver # F:usb/usbaudio.c:1.115->1.116 # F:usb/usbaudio.h:1.36->1.37 # F:usb/usbmidi.c:1.37->1.38 # F:usb/usbquirks.h:1.40->1.41 # L:Rewrote USB MIDI protocol handling code to use callbacks # L:for each protocol; # L:added support for Novation and MOTU protocols; # L:changed detection code to allow interrupt endpoints. # Signed-off-by: Clemens Ladisch # # sound/usb/usbaudio.c # 2005/02/02 05:54:07+01:00 perex@suse.cz +2 -0 # [ALSA] Novation and MOTU USB MIDI support # # D:2005/02/02 12:54:07 # C:USB generic driver # F:usb/usbaudio.c:1.115->1.116 # F:usb/usbaudio.h:1.36->1.37 # F:usb/usbmidi.c:1.37->1.38 # F:usb/usbquirks.h:1.40->1.41 # L:Rewrote USB MIDI protocol handling code to use callbacks # L:for each protocol; # L:added support for Novation and MOTU protocols; # L:changed detection code to allow interrupt endpoints. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 15:00:22+01:00 perex@suse.cz # [ALSA] simplify snd_usbmidi_count_bits() # # USB generic driver # This makes the bit counting code smaller and simpler. # # Signed-off-by: Charles C. Bennett # Signed-off-by: Clemens Ladisch # # sound/usb/usbmidi.c # 2005/02/02 05:45:33+01:00 perex@suse.cz +4 -4 # [ALSA] simplify snd_usbmidi_count_bits() # # D:2005/02/02 12:45:33 # C:USB generic driver # F:usb/usbmidi.c:1.36->1.37 # L:This makes the bit counting code smaller and simpler. # Signed-off-by: Charles C. Bennett # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 14:59:12+01:00 perex@suse.cz # [ALSA] capture EXTINs with multichannel device # # EMU10K1/EMU10K2 driver # This patch changes the emu10k1 multichannel capture device (hw:x,2) to # capture the 16 external inputs by default. This involves adding DSP # code to route the EXTINs to the FXBUS2 (EFX capture) channels and # setting the corresponding FXWC bits by default. # # This allows capturing multiple inputs simultaneously. It completely # bypasses the capture controls of the mixer. With my Audigy2 ZS I can # capture LineIn, Line2, and Aux2 at the same time (6 channels). # # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emupcm.c # 2005/02/02 04:52:46+01:00 perex@suse.cz +12 -2 # [ALSA] capture EXTINs with multichannel device # # D:2005/02/02 11:52:45 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.53->1.54 # F:pci/emu10k1/emufx.c:1.67->1.68 # F:pci/emu10k1/emupcm.c:1.35->1.36 # L:This patch changes the emu10k1 multichannel capture device (hw:x,2) to # L:capture the 16 external inputs by default. This involves adding DSP # L:code to route the EXTINs to the FXBUS2 (EFX capture) channels and # L:setting the corresponding FXWC bits by default. # L: # L:This allows capturing multiple inputs simultaneously. It completely # L:bypasses the capture controls of the mixer. With my Audigy2 ZS I can # L:capture LineIn, Line2, and Aux2 at the same time (6 channels). # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emufx.c # 2005/02/02 04:52:46+01:00 perex@suse.cz +23 -0 # [ALSA] capture EXTINs with multichannel device # # D:2005/02/02 11:52:45 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.53->1.54 # F:pci/emu10k1/emufx.c:1.67->1.68 # F:pci/emu10k1/emupcm.c:1.35->1.36 # L:This patch changes the emu10k1 multichannel capture device (hw:x,2) to # L:capture the 16 external inputs by default. This involves adding DSP # L:code to route the EXTINs to the FXBUS2 (EFX capture) channels and # L:setting the corresponding FXWC bits by default. # L: # L:This allows capturing multiple inputs simultaneously. It completely # L:bypasses the capture controls of the mixer. With my Audigy2 ZS I can # L:capture LineIn, Line2, and Aux2 at the same time (6 channels). # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # include/sound/emu10k1.h # 2005/02/02 04:52:45+01:00 perex@suse.cz +11 -4 # [ALSA] capture EXTINs with multichannel device # # D:2005/02/02 11:52:45 # C:EMU10K1/EMU10K2 driver # F:include/emu10k1.h:1.53->1.54 # F:pci/emu10k1/emufx.c:1.67->1.68 # F:pci/emu10k1/emupcm.c:1.35->1.36 # L:This patch changes the emu10k1 multichannel capture device (hw:x,2) to # L:capture the 16 external inputs by default. This involves adding DSP # L:code to route the EXTINs to the FXBUS2 (EFX capture) channels and # L:setting the corresponding FXWC bits by default. # L: # L:This allows capturing multiple inputs simultaneously. It completely # L:bypasses the capture controls of the mixer. With my Audigy2 ZS I can # L:capture LineIn, Line2, and Aux2 at the same time (6 channels). # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:57:56+01:00 perex@suse.cz # [ALSA] Add quirk for LEGEND ZhaoYang 3100CF # # Maestro3 driver # Added a quirk entry for LEGEND ZhaoYang 3100CF. # # Signed-off-by: Takashi Iwai # # sound/pci/maestro3.c # 2005/02/01 11:27:39+01:00 perex@suse.cz +7 -0 # [ALSA] Add quirk for LEGEND ZhaoYang 3100CF # # D:2005/02/01 18:27:39 # C:Maestro3 driver # F:pci/maestro3.c:1.69->1.70 # L:Added a quirk entry for LEGEND ZhaoYang 3100CF. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:56:43+01:00 perex@suse.cz # [ALSA] replace interruptible_sleep_on_timeout() with wait_event_interruptible_timeout() # # RawMidi Midlevel # Use wai_event_interruptible_timeout() instead of deprecated # interruptible_sleep_on_timeout(). Patch is compile-tested. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/core/rawmidi.c # 2005/01/31 07:58:05+01:00 perex@suse.cz +9 -11 # [ALSA] replace interruptible_sleep_on_timeout() with wait_event_interruptible_timeout() # # D:2005/01/31 14:58:05 # C:RawMidi Midlevel # F:core/rawmidi.c:1.53->1.54 # L:Use wai_event_interruptible_timeout() instead of deprecated # L:interruptible_sleep_on_timeout(). Patch is compile-tested. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:55:33+01:00 perex@suse.cz # [ALSA] Kconfig: cleanup sound menu # # ALSA Core # This properly indents the sound menu. # # Signed-off-by: Roman Zippel # Signed-off-by: Takashi Iwai # # sound/core/Kconfig # 2005/01/31 07:48:50+01:00 perex@suse.cz +7 -1 # [ALSA] Kconfig: cleanup sound menu # # D:2005/01/31 14:48:50 # C:ALSA Core # F:core/Kconfig:1.9->1.10 # L:This properly indents the sound menu. # Signed-off-by: Roman Zippel # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:54:24+01:00 perex@suse.cz # [ALSA] hdsp ghost midi device fix # # RME HDSP driver # * Prevents the creation of a second midi device for cards with only # one midi I/O # # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # sound/pci/rme9652/hdsp.c # 2005/01/31 06:41:30+01:00 perex@suse.cz +8 -5 # [ALSA] hdsp ghost midi device fix # # D:2005/01/31 13:41:30 # C:RME HDSP driver # F:pci/rme9652/hdsp.c:1.81->1.82 # L:* Prevents the creation of a second midi device for cards with only # L: one midi I/O # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:53:15+01:00 perex@suse.cz # [ALSA] Fix 32bit calls to snd_pcm_channel_info() # # PCM Midlevel # Fix 32-bit calls to snd_pcm_channel_info(). # # Signed-off-by: Brian Gerst # Signed-off-by: Takashi Iwai # # sound/core/pcm_native.c # 2005/01/31 06:38:39+01:00 perex@suse.cz +16 -10 # [ALSA] Fix 32bit calls to snd_pcm_channel_info() # # D:2005/01/31 13:38:39 # C:PCM Midlevel # F:core/pcm_native.c:1.113->1.114 # L:Fix 32-bit calls to snd_pcm_channel_info(). # Signed-off-by: Brian Gerst # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:52:11+01:00 perex@suse.cz # [ALSA] Fix compile error (due to last suspend/resume fix) # # PPC PMAC driver # Fixed the forgotten caller of suspend/resume callbacks to follow # the recent PM fixes. # # Signed-off-by: Takashi Iwai # # sound/ppc/pmac.c # 2005/01/31 03:41:30+01:00 perex@suse.cz +2 -2 # [ALSA] Fix compile error (due to last suspend/resume fix) # # D:2005/01/31 10:41:30 # C:PPC PMAC driver # F:ppc/pmac.c:1.44->1.45 # L:Fixed the forgotten caller of suspend/resume callbacks to follow # L:the recent PM fixes. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:51:01+01:00 perex@suse.cz # [ALSA] intel8x0 - fix for broken PCI ID define for ICH6 # # Intel8x0 driver # Patch-level: High # # Signed-off-by: Jean Delvare # Signed-off-by: Jaroslav Kysela # # sound/pci/intel8x0.c # 2005/01/31 03:04:10+01:00 perex@suse.cz +3 -3 # [ALSA] intel8x0 - fix for broken PCI ID define for ICH6 # # D:2005/01/31 10:04:10 # C:Intel8x0 driver # F:pci/intel8x0.c:1.192->1.193 # L:Patch-level: High # Signed-off-by: Jean Delvare # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/02/14 14:49:48+01:00 perex@suse.cz # [ALSA] intel8x0 - fixed timeout in the 'get current DMA pointer' routine # # Intel8x0 driver # Patch-level: High # # Signed-off-by: Wei Ni # Signed-off-by: Jaroslav Kysela # # sound/pci/intel8x0.c # 2005/01/31 02:50:36+01:00 perex@suse.cz +5 -3 # [ALSA] intel8x0 - fixed timeout in the 'get current DMA pointer' routine # # D:2005/01/31 09:50:36 # C:Intel8x0 driver # F:pci/intel8x0.c:1.191->1.192 # L:Patch-level: High # Signed-off-by: Wei Ni # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/02/14 14:48:36+01:00 perex@suse.cz # [ALSA] Fix suspend/resume functions # # ALSA Core # Fix the suspend/resume callback functions to follow the last change. # (This fix was missing in the last patch.) # # Signed-off-by: Takashi Iwai # # sound/core/init.c # 2005/01/28 13:18:39+01:00 perex@suse.cz +2 -2 # [ALSA] Fix suspend/resume functions # # D:2005/01/28 20:18:39 # C:ALSA Core # F:core/init.c:1.59->1.60 # L:Fix the suspend/resume callback functions to follow the last change. # L:(This fix was missing in the last patch.) # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:47:25+01:00 perex@suse.cz # [ALSA] Fix inclusion of pm.h # # ALSA Core # Added the missing inclusion of linux/pm.h. # # Signed-off-by: Takashi Iwai # # include/sound/core.h # 2005/01/28 13:13:27+01:00 perex@suse.cz +1 -0 # [ALSA] Fix inclusion of pm.h # # D:2005/01/28 20:13:27 # C:ALSA Core # F:include/core.h:1.66->1.67 # L:Added the missing inclusion of linux/pm.h. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:46:09+01:00 perex@suse.cz # [ALSA] Fix resume callback # # HDA Codec driver # Fixed resume callback to follow the recent change of PM callbacks. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_realtek.c # 2005/01/28 12:48:54+01:00 perex@suse.cz +1 -1 # [ALSA] Fix resume callback # # D:2005/01/28 19:48:54 # C:HDA Codec driver # F:pci/hda/patch_cmedia.c:1.1->1.2 # F:pci/hda/patch_realtek.c:1.1->1.2 # L:Fixed resume callback to follow the recent change of PM callbacks. # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_cmedia.c # 2005/01/28 12:48:54+01:00 perex@suse.cz +1 -1 # [ALSA] Fix resume callback # # D:2005/01/28 19:48:54 # C:HDA Codec driver # F:pci/hda/patch_cmedia.c:1.1->1.2 # F:pci/hda/patch_realtek.c:1.1->1.2 # L:Fixed resume callback to follow the recent change of PM callbacks. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:44:45+01:00 perex@suse.cz # [ALSA] Remove unused variable # # USB USX2Y # Removed an unused variable to fix a compile warning. # # Signed-off-by: Takashi Iwai # # sound/usb/usx2y/usbusx2yaudio.c # 2005/01/28 12:39:48+01:00 perex@suse.cz +0 -1 # [ALSA] Remove unused variable # # D:2005/01/28 19:39:48 # C:USB USX2Y # F:usb/usx2y/usbusx2yaudio.c:1.10->1.11 # L:Removed an unused variable to fix a compile warning. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:43:33+01:00 perex@suse.cz # [ALSA] Fix descriptions about suspend/resume callbacks # # Documentation # Fixed the descriptions about suspend/resume callbacks. # The suspend callback takes pm_message_t argument, and resume takes no # extra argument now. # # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/hda_codec.txt # 2005/01/28 12:36:32+01:00 perex@suse.cz +2 -2 # [ALSA] Fix descriptions about suspend/resume callbacks # # D:2005/01/28 19:36:32 # C:Documentation # F:Documentation/hda_codec.txt:1.1->1.2 # F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.47->1.48 # L:Fixed the descriptions about suspend/resume callbacks. # L:The suspend callback takes pm_message_t argument, and resume takes no # L:extra argument now. # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl # 2005/01/28 12:36:33+01:00 perex@suse.cz +3 -3 # [ALSA] Fix descriptions about suspend/resume callbacks # # D:2005/01/28 19:36:32 # C:Documentation # F:Documentation/hda_codec.txt:1.1->1.2 # F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.47->1.48 # L:Fixed the descriptions about suspend/resume callbacks. # L:The suspend callback takes pm_message_t argument, and resume takes no # L:extra argument now. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:42:16+01:00 perex@suse.cz # [ALSA] driver model type fixes for ALSA # # SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # Fixes by Pavel Machek : # suspend() routines no longer get u32 as their parameter (they get # pm_message_t, which is u32 for now, but will change in 2.6.12 or # so). This fixes ALSA to notice this, and uses constants with right # types where appropriate. It results in no code changes. [Best results # will be when patching against latest -mm, you may get some warnings if # you patch it into older kernel, but it should still do the right # thing.] Please apply, # Pavel # # [In addition, suspend callback type is changed to follow to the standard # style taking no state argument -- Takashi] # # Signed-off-by: Takashi Iwai # # sound/ppc/pmac.c # 2005/01/28 12:34:08+01:00 perex@suse.cz +4 -4 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pcmcia/vx/vx_entry.c # 2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pcmcia/pdaudiocf/pdaudiocf_core.c # 2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pcmcia/pdaudiocf/pdaudiocf.h # 2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pcmcia/pdaudiocf/pdaudiocf.c # 2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/ymfpci/ymfpci_main.c # 2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/via82xx_modem.c # 2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/via82xx.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/trident/trident_main.c # 2005/01/28 12:34:08+01:00 perex@suse.cz +4 -4 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/nm256/nm256.c # 2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/maestro3.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0m.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_intel.c # 2005/01/28 12:34:07+01:00 perex@suse.cz +3 -3 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.h # 2005/01/28 12:34:07+01:00 perex@suse.cz +4 -4 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.c # 2005/01/28 12:34:07+01:00 perex@suse.cz +3 -3 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/es1968.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/es1938.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/cs46xx/cs46xx_lib.c # 2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/cs4281.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +4 -4 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/atiixp_modem.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/atiixp.c # 2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/pci/ali5451/ali5451.c # 2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/isa/opl3sa2.c # 2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/isa/es18xx.c # 2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/isa/cs423x/cs4231_lib.c # 2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/isa/ad1848/ad1848_lib.c # 2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/drivers/vx/vx_core.c # 2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/core/init.c # 2005/01/28 12:34:04+01:00 perex@suse.cz +7 -11 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/core/control.c # 2005/01/28 12:34:04+01:00 perex@suse.cz +2 -4 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # sound/arm/sa11xx-uda1341.c # 2005/01/28 12:34:04+01:00 perex@suse.cz +3 -3 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # include/sound/core.h # 2005/01/28 12:34:05+01:00 perex@suse.cz +7 -7 # [ALSA] driver model type fixes for ALSA # # D:2005/01/28 19:34:04 # C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core # C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver # C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver # C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver # C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver # C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver # C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver # F:arm/sa11xx-uda1341.c:1.20->1.21 # F:core/control.c:1.56->1.57 # F:core/init.c:1.58->1.59 # F:drivers/vx/vx_core.c:1.14->1.15 # F:include/core.h:1.65->1.66 # F:isa/es18xx.c:1.53->1.54 # F:isa/opl3sa2.c:1.42->1.43 # F:isa/ad1848/ad1848_lib.c:1.39->1.40 # F:isa/cs423x/cs4231_lib.c:1.47->1.48 # F:pci/atiixp.c:1.31->1.32 # F:pci/atiixp_modem.c:1.14->1.15 # F:pci/cs4281.c:1.69->1.70 # F:pci/es1938.c:1.45->1.46 # F:pci/es1968.c:1.82->1.83 # F:pci/intel8x0.c:1.190->1.191 # F:pci/intel8x0m.c:1.26->1.27 # F:pci/maestro3.c:1.68->1.69 # F:pci/via82xx.c:1.135->1.136 # F:pci/via82xx_modem.c:1.4->1.5 # F:pci/ali5451/ali5451.c:1.60->1.61 # F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 # F:pci/hda/hda_codec.c:1.1->1.2 # F:pci/hda/hda_codec.h:1.1->1.2 # F:pci/hda/hda_intel.c:1.2->1.3 # F:pci/nm256/nm256.c:1.58->1.59 # F:pci/trident/trident_main.c:1.69->1.70 # F:pci/ymfpci/ymfpci_main.c:1.64->1.65 # F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 # F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 # F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 # F:pcmcia/vx/vx_entry.c:1.8->1.9 # F:ppc/pmac.c:1.43->1.44 # L:Fixes by Pavel Machek : # L:suspend() routines no longer get u32 as their parameter (they get # L:pm_message_t, which is u32 for now, but will change in 2.6.12 or # L:so). This fixes ALSA to notice this, and uses constants with right # L:types where appropriate. It results in no code changes. [Best results # L:will be when patching against latest -mm, you may get some warnings if # L:you patch it into older kernel, but it should still do the right # L:thing.] Please apply, # L: Pavel # L: # L:[In addition, suspend callback type is changed to follow to the standard # L: style taking no state argument -- Takashi] # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:40:49+01:00 perex@suse.cz # [ALSA] use cached idVendor/idProduct values # # USB generic driver # use the vendor/product IDs in the state structure instead of # reading them again from the device # # Signed-off-by: Clemens Ladisch # # sound/usb/usbmixer.c # 2005/01/28 10:48:14+01:00 perex@suse.cz +1 -1 # [ALSA] use cached idVendor/idProduct values # # D:2005/01/28 17:48:14 # C:USB generic driver # F:usb/usbmixer.c:1.35->1.36 # L:use the vendor/product IDs in the state structure instead of # L:reading them again from the device # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/02/14 14:39:40+01:00 perex@suse.cz # [ALSA] Set default index of modem and bt87x drivers to -2 # # Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver # VIA82xx-modem driver # Set the default index value of modem and bt87x drivers to -2 so that # the first slot is excluded when no index option is given. # This gives other uadio drivers a chance to put them as the primary # driver. # # Signed-off-by: Takashi Iwai # # sound/pci/via82xx_modem.c # 2005/01/28 10:02:15+01:00 perex@suse.cz +1 -1 # [ALSA] Set default index of modem and bt87x drivers to -2 # # D:2005/01/28 17:02:13 # C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver # C:VIA82xx-modem driver # F:Documentation/ALSA-Configuration.txt:1.67->1.68 # F:pci/atiixp_modem.c:1.13->1.14 # F:pci/bt87x.c:1.18->1.19 # F:pci/intel8x0m.c:1.25->1.26 # F:pci/via82xx_modem.c:1.3->1.4 # L:Set the default index value of modem and bt87x drivers to -2 so that # L:the first slot is excluded when no index option is given. # L:This gives other uadio drivers a chance to put them as the primary # L:driver. # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0m.c # 2005/01/28 10:02:15+01:00 perex@suse.cz +1 -1 # [ALSA] Set default index of modem and bt87x drivers to -2 # # D:2005/01/28 17:02:13 # C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver # C:VIA82xx-modem driver # F:Documentation/ALSA-Configuration.txt:1.67->1.68 # F:pci/atiixp_modem.c:1.13->1.14 # F:pci/bt87x.c:1.18->1.19 # F:pci/intel8x0m.c:1.25->1.26 # F:pci/via82xx_modem.c:1.3->1.4 # L:Set the default index value of modem and bt87x drivers to -2 so that # L:the first slot is excluded when no index option is given. # L:This gives other uadio drivers a chance to put them as the primary # L:driver. # Signed-off-by: Takashi Iwai # # sound/pci/bt87x.c # 2005/01/28 10:02:15+01:00 perex@suse.cz +1 -1 # [ALSA] Set default index of modem and bt87x drivers to -2 # # D:2005/01/28 17:02:13 # C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver # C:VIA82xx-modem driver # F:Documentation/ALSA-Configuration.txt:1.67->1.68 # F:pci/atiixp_modem.c:1.13->1.14 # F:pci/bt87x.c:1.18->1.19 # F:pci/intel8x0m.c:1.25->1.26 # F:pci/via82xx_modem.c:1.3->1.4 # L:Set the default index value of modem and bt87x drivers to -2 so that # L:the first slot is excluded when no index option is given. # L:This gives other uadio drivers a chance to put them as the primary # L:driver. # Signed-off-by: Takashi Iwai # # sound/pci/atiixp_modem.c # 2005/01/28 10:02:14+01:00 perex@suse.cz +1 -1 # [ALSA] Set default index of modem and bt87x drivers to -2 # # D:2005/01/28 17:02:13 # C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver # C:VIA82xx-modem driver # F:Documentation/ALSA-Configuration.txt:1.67->1.68 # F:pci/atiixp_modem.c:1.13->1.14 # F:pci/bt87x.c:1.18->1.19 # F:pci/intel8x0m.c:1.25->1.26 # F:pci/via82xx_modem.c:1.3->1.4 # L:Set the default index value of modem and bt87x drivers to -2 so that # L:the first slot is excluded when no index option is given. # L:This gives other uadio drivers a chance to put them as the primary # L:driver. # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/01/28 10:02:13+01:00 perex@suse.cz +12 -0 # [ALSA] Set default index of modem and bt87x drivers to -2 # # D:2005/01/28 17:02:13 # C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver # C:VIA82xx-modem driver # F:Documentation/ALSA-Configuration.txt:1.67->1.68 # F:pci/atiixp_modem.c:1.13->1.14 # F:pci/bt87x.c:1.18->1.19 # F:pci/intel8x0m.c:1.25->1.26 # F:pci/via82xx_modem.c:1.3->1.4 # L:Set the default index value of modem and bt87x drivers to -2 so that # L:the first slot is excluded when no index option is given. # L:This gives other uadio drivers a chance to put them as the primary # L:driver. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:38:31+01:00 perex@suse.cz # [ALSA] Interpret negative index as bitmask of permissible indexes # # Documentation,ALSA Core # Currently arguments of the 'index' option from 0 through SNDRV_CARDS-1 # force a module to take the specified index. Index -1 makes the module # take the first available index. This patch extends this convention so # that a negative index value is interpreted as a bitmask of the # permitted indexes. Special cases: # # -1 0xffffffff 0 and up # -2 0xfffffffe 1 and up # -4 0xfffffffc 2 and up # ... # # The patch includes also corrections of ALSA-Configuration.txt document. # # Signed-off-by: Thomas Hood # Signed-off-by: Takashi Iwai # # sound/core/init.c # 2005/01/28 09:55:34+01:00 perex@suse.cz +4 -7 # [ALSA] Interpret negative index as bitmask of permissible indexes # # D:2005/01/28 16:55:33 # C:Documentation,ALSA Core # F:Documentation/ALSA-Configuration.txt:1.66->1.67 # F:core/init.c:1.57->1.58 # L:Currently arguments of the 'index' option from 0 through SNDRV_CARDS-1 # L:force a module to take the specified index. Index -1 makes the module # L:take the first available index. This patch extends this convention so # L:that a negative index value is interpreted as a bitmask of the # L:permitted indexes. Special cases: # L: # L: -1 0xffffffff 0 and up # L: -2 0xfffffffe 1 and up # L: -4 0xfffffffc 2 and up # L: ... # L: # L:The patch includes also corrections of ALSA-Configuration.txt document. # Signed-off-by: Thomas Hood # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/01/28 09:55:33+01:00 perex@suse.cz +114 -107 # [ALSA] Interpret negative index as bitmask of permissible indexes # # D:2005/01/28 16:55:33 # C:Documentation,ALSA Core # F:Documentation/ALSA-Configuration.txt:1.66->1.67 # F:core/init.c:1.57->1.58 # L:Currently arguments of the 'index' option from 0 through SNDRV_CARDS-1 # L:force a module to take the specified index. Index -1 makes the module # L:take the first available index. This patch extends this convention so # L:that a negative index value is interpreted as a bitmask of the # L:permitted indexes. Special cases: # L: # L: -1 0xffffffff 0 and up # L: -2 0xfffffffe 1 and up # L: -4 0xfffffffc 2 and up # L: ... # L: # L:The patch includes also corrections of ALSA-Configuration.txt document. # Signed-off-by: Thomas Hood # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:37:21+01:00 perex@suse.cz # [ALSA] Changes 'Music' to 'Synth' in mixer control names # # EMU10K1/EMU10K2 driver # Changes 'Music' to 'Synth' in mixer control names # # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # sound/pci/emu10k1/emufx.c # 2005/01/28 08:33:10+01:00 perex@suse.cz +9 -9 # [ALSA] Changes 'Music' to 'Synth' in mixer control names # # D:2005/01/28 15:33:10 # C:EMU10K1/EMU10K2 driver # F:pci/emu10k1/emufx.c:1.66->1.67 # L:Changes 'Music' to 'Synth' in mixer control names # Signed-off-by: Lee Revell # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:36:10+01:00 perex@suse.cz # [ALSA] HDSP fixes # # Documentation,RME HDSP driver # * init sequence cleanup and firmware upload related bugfixes # * more robust revision detection scheme # (should transparently handle new revisions) # * allow hdsploader and the kernel fw loader to coexist # this is useful for cardbus user who compiled the driver in-kernel # (userspace may not be ready to upload the firmware when the card # is probed) # * removed confusing and obsolete passthru option (was interfering # with the mixer when opening the device for capture or playback) # this change requires a recompile of the userspace tools against # the patched hdsp.h # * removed confusing and obsolete line_outs_monitor module param # * made precise_ptr the default behaviour, and runtime tweakable # (removed corresponding module param) # * add an alsa ctl to disable the use of the midi tasklet, and # process midi data in the interrupt handler # (using the tasklet is still the default) # this is mainly intended for users of Ingo Molnar's RT patch # * metering fix for Multiface/Digiface users (closes ALSA BUG #0000801) # * small endianness fix # * ALSA-Configuration.txt HDSP entry update # * error messages cleanup # # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # sound/pci/rme9652/hdsp.c # 2005/01/28 08:12:41+01:00 perex@suse.cz +235 -271 # [ALSA] HDSP fixes # # D:2005/01/28 15:12:41 # C:Documentation,RME HDSP driver # F:Documentation/ALSA-Configuration.txt:1.65->1.66 # F:pci/rme9652/hdsp.c:1.80->1.81 # L:* init sequence cleanup and firmware upload related bugfixes # L:* more robust revision detection scheme # L: (should transparently handle new revisions) # L:* allow hdsploader and the kernel fw loader to coexist # L: this is useful for cardbus user who compiled the driver in-kernel # L: (userspace may not be ready to upload the firmware when the card # L: is probed) # L:* removed confusing and obsolete passthru option (was interfering # L: with the mixer when opening the device for capture or playback) # L: this change requires a recompile of the userspace tools against # L: the patched hdsp.h # L:* removed confusing and obsolete line_outs_monitor module param # L:* made precise_ptr the default behaviour, and runtime tweakable # L: (removed corresponding module param) # L:* add an alsa ctl to disable the use of the midi tasklet, and # L: process midi data in the interrupt handler # L: (using the tasklet is still the default) # L: this is mainly intended for users of Ingo Molnar's RT patch # L:* metering fix for Multiface/Digiface users (closes ALSA BUG #0000801) # L:* small endianness fix # L:* ALSA-Configuration.txt HDSP entry update # L:* error messages cleanup # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/01/28 08:12:41+01:00 perex@suse.cz +0 -7 # [ALSA] HDSP fixes # # D:2005/01/28 15:12:41 # C:Documentation,RME HDSP driver # F:Documentation/ALSA-Configuration.txt:1.65->1.66 # F:pci/rme9652/hdsp.c:1.80->1.81 # L:* init sequence cleanup and firmware upload related bugfixes # L:* more robust revision detection scheme # L: (should transparently handle new revisions) # L:* allow hdsploader and the kernel fw loader to coexist # L: this is useful for cardbus user who compiled the driver in-kernel # L: (userspace may not be ready to upload the firmware when the card # L: is probed) # L:* removed confusing and obsolete passthru option (was interfering # L: with the mixer when opening the device for capture or playback) # L: this change requires a recompile of the userspace tools against # L: the patched hdsp.h # L:* removed confusing and obsolete line_outs_monitor module param # L:* made precise_ptr the default behaviour, and runtime tweakable # L: (removed corresponding module param) # L:* add an alsa ctl to disable the use of the midi tasklet, and # L: process midi data in the interrupt handler # L: (using the tasklet is still the default) # L: this is mainly intended for users of Ingo Molnar's RT patch # L:* metering fix for Multiface/Digiface users (closes ALSA BUG #0000801) # L:* small endianness fix # L:* ALSA-Configuration.txt HDSP entry update # L:* error messages cleanup # Signed-off-by: Thomas Charbonnel # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:34:58+01:00 perex@suse.cz # [ALSA] Remove pm_register/pm_unregister # # SA11xx UDA1341 driver,ALSA Core,ISA # Removed pm_register() and pm_unregister(). # Use platform_device for suspend/resume, instead. # # The current implemention is still a hack. The whole ISA drivers should # be rewritten with a proper bus definition. # # Signed-off-by: Takashi Iwai # # sound/isa/Kconfig # 2005/01/28 07:49:59+01:00 perex@suse.cz +6 -0 # [ALSA] Remove pm_register/pm_unregister # # D:2005/01/28 14:49:59 # C:SA11xx UDA1341 driver,ALSA Core,ISA # F:arm/sa11xx-uda1341.c:1.19->1.20 # F:core/Kconfig:1.8->1.9 # F:core/init.c:1.56->1.57 # F:core/sound.c:1.72->1.73 # F:include/core.h:1.64->1.65 # F:isa/Kconfig:1.14->1.15 # L:Removed pm_register() and pm_unregister(). # L:Use platform_device for suspend/resume, instead. # L: # L:The current implemention is still a hack. The whole ISA drivers should # L:be rewritten with a proper bus definition. # Signed-off-by: Takashi Iwai # # sound/core/sound.c # 2005/01/28 07:49:59+01:00 perex@suse.cz +3 -1 # [ALSA] Remove pm_register/pm_unregister # # D:2005/01/28 14:49:59 # C:SA11xx UDA1341 driver,ALSA Core,ISA # F:arm/sa11xx-uda1341.c:1.19->1.20 # F:core/Kconfig:1.8->1.9 # F:core/init.c:1.56->1.57 # F:core/sound.c:1.72->1.73 # F:include/core.h:1.64->1.65 # F:isa/Kconfig:1.14->1.15 # L:Removed pm_register() and pm_unregister(). # L:Use platform_device for suspend/resume, instead. # L: # L:The current implemention is still a hack. The whole ISA drivers should # L:be rewritten with a proper bus definition. # Signed-off-by: Takashi Iwai # # sound/core/init.c # 2005/01/28 07:49:59+01:00 perex@suse.cz +108 -26 # [ALSA] Remove pm_register/pm_unregister # # D:2005/01/28 14:49:59 # C:SA11xx UDA1341 driver,ALSA Core,ISA # F:arm/sa11xx-uda1341.c:1.19->1.20 # F:core/Kconfig:1.8->1.9 # F:core/init.c:1.56->1.57 # F:core/sound.c:1.72->1.73 # F:include/core.h:1.64->1.65 # F:isa/Kconfig:1.14->1.15 # L:Removed pm_register() and pm_unregister(). # L:Use platform_device for suspend/resume, instead. # L: # L:The current implemention is still a hack. The whole ISA drivers should # L:be rewritten with a proper bus definition. # Signed-off-by: Takashi Iwai # # sound/core/Kconfig # 2005/01/28 07:49:59+01:00 perex@suse.cz +2 -0 # [ALSA] Remove pm_register/pm_unregister # # D:2005/01/28 14:49:59 # C:SA11xx UDA1341 driver,ALSA Core,ISA # F:arm/sa11xx-uda1341.c:1.19->1.20 # F:core/Kconfig:1.8->1.9 # F:core/init.c:1.56->1.57 # F:core/sound.c:1.72->1.73 # F:include/core.h:1.64->1.65 # F:isa/Kconfig:1.14->1.15 # L:Removed pm_register() and pm_unregister(). # L:Use platform_device for suspend/resume, instead. # L: # L:The current implemention is still a hack. The whole ISA drivers should # L:be rewritten with a proper bus definition. # Signed-off-by: Takashi Iwai # # sound/arm/sa11xx-uda1341.c # 2005/01/28 07:49:59+01:00 perex@suse.cz +2 -2 # [ALSA] Remove pm_register/pm_unregister # # D:2005/01/28 14:49:59 # C:SA11xx UDA1341 driver,ALSA Core,ISA # F:arm/sa11xx-uda1341.c:1.19->1.20 # F:core/Kconfig:1.8->1.9 # F:core/init.c:1.56->1.57 # F:core/sound.c:1.72->1.73 # F:include/core.h:1.64->1.65 # F:isa/Kconfig:1.14->1.15 # L:Removed pm_register() and pm_unregister(). # L:Use platform_device for suspend/resume, instead. # L: # L:The current implemention is still a hack. The whole ISA drivers should # L:be rewritten with a proper bus definition. # Signed-off-by: Takashi Iwai # # include/sound/core.h # 2005/01/28 07:49:59+01:00 perex@suse.cz +15 -15 # [ALSA] Remove pm_register/pm_unregister # # D:2005/01/28 14:49:59 # C:SA11xx UDA1341 driver,ALSA Core,ISA # F:arm/sa11xx-uda1341.c:1.19->1.20 # F:core/Kconfig:1.8->1.9 # F:core/init.c:1.56->1.57 # F:core/sound.c:1.72->1.73 # F:include/core.h:1.64->1.65 # F:isa/Kconfig:1.14->1.15 # L:Removed pm_register() and pm_unregister(). # L:Use platform_device for suspend/resume, instead. # L: # L:The current implemention is still a hack. The whole ISA drivers should # L:be rewritten with a proper bus definition. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:33:45+01:00 perex@suse.cz # [ALSA] Remove descriptions of obsolete options # # Documentation # Removed descriptions of obsolete irq_mask and irq_list options for # vxpocket, vxp440 and pdaudiocf drivers. # # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/01/28 07:42:55+01:00 perex@suse.cz +0 -16 # [ALSA] Remove descriptions of obsolete options # # D:2005/01/28 14:42:55 # C:Documentation # F:Documentation/ALSA-Configuration.txt:1.64->1.65 # L:Removed descriptions of obsolete irq_mask and irq_list options for # L:vxpocket, vxp440 and pdaudiocf drivers. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/02/14 14:32:27+01:00 perex@suse.cz # [ALSA] Ascii chars only # # RME HDSP driver # # # Signed-off-by: Jaroslav Kysela # # sound/pci/rme9652/hdsp.c # 2005/02/14 14:31:38+01:00 perex@suse.cz +1 -1 # [ALSA] Ascii chars only # # D:2005/01/28 10:13:37 # C:RME HDSP driver # F:pci/rme9652/hdsp.c:1.79->1.80 # L: # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/02/14 14:28:53+01:00 perex@suse.cz # [ALSA] Add newline to printk # # ALSA Core # Added the newline to printk error output. # # Signed-off-by: Takashi Iwai # # sound/core/init.c # 2005/01/25 07:27:34+01:00 perex@suse.cz +1 -1 # [ALSA] Add newline to printk # # ALSA Core # Added the newline to printk error output. # # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/27 08:20:45+01:00 perex@suse.cz # [ALSA] Removed file added by mistake # # Removed include/sound/version.h~ # # BitKeeper/deleted/.del-version.h~~37c78b8aa77b0731 # 2005/01/27 08:15:16+01:00 perex@suse.cz +0 -0 # Delete: include/sound/version.h~ # # ChangeSet # 2005/01/25 20:52:17+01:00 perex@suse.cz # [ALSA] replace schedule_timeout() with msleep() # # EMU8000 driver # Use msleep() instead of schedule_timeout() to guarantee the task # delays as expected. # # Signed-off-by: Takashi Iwai # # sound/isa/sb/emu8000.c # 2005/01/24 08:00:18+01:00 perex@suse.cz +2 -2 # [ALSA] replace schedule_timeout() with msleep() # # D:2005/01/24 15:00:18 # C:EMU8000 driver # F:isa/sb/emu8000.c:1.24->1.25 # L:Use msleep() instead of schedule_timeout() to guarantee the task # L:delays as expected. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:50:28+01:00 perex@suse.cz # [ALSA] insert set_current_state() before schedule_timeout() # # Wavefront drivers # Insert set_current_state() before schedule_timeout(). Without the # insertion, schedule_timeout() returns immediately, resulting in an # effective busy-wait. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/isa/wavefront/wavefront_synth.c # 2005/01/24 07:59:27+01:00 perex@suse.cz +1 -0 # [ALSA] insert set_current_state() before schedule_timeout() # # D:2005/01/24 14:59:27 # C:Wavefront drivers # F:isa/wavefront/wavefront_synth.c:1.23->1.24 # L:Insert set_current_state() before schedule_timeout(). Without the # L:insertion, schedule_timeout() returns immediately, resulting in an # L:effective busy-wait. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:48:58+01:00 perex@suse.cz # [ALSA] replace schedule_timeout() with msleep_interruptible() # # GUS Library # Use msleep_interruptible() instead of custom wait code involving # schedule_timeout() to guarantee the task delays as expected. This also # removes a dependence on the value of HZ. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/isa/gus/gus_reset.c # 2005/01/24 07:58:37+01:00 perex@suse.cz +1 -6 # [ALSA] replace schedule_timeout() with msleep_interruptible() # # D:2005/01/24 14:58:37 # C:GUS Library # F:isa/gus/gus_reset.c:1.7->1.8 # L:Use msleep_interruptible() instead of custom wait code involving # L:schedule_timeout() to guarantee the task delays as expected. This also # L:removes a dependence on the value of HZ. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:47:19+01:00 perex@suse.cz # [ALSA] insert set_current_state() before schedule_timeout() # # GUS Library # Insert set_current_state() before schedule_timeout(). Without the # insertion, schedule_timeout() returns immediately. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/isa/gus/gus_pcm.c # 2005/01/24 07:57:51+01:00 perex@suse.cz +1 -0 # [ALSA] insert set_current_state() before schedule_timeout() # # D:2005/01/24 14:57:51 # C:GUS Library # F:isa/gus/gus_pcm.c:1.23->1.24 # L:Insert set_current_state() before schedule_timeout(). Without the # L:insertion, schedule_timeout() returns immediately. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:41:00+01:00 perex@suse.cz # [ALSA] replace schedule_timeout() with msleep() # # Digigram VX core # Use msleep() instead of schedule_timeout() to guarantee the task # delays as expected. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/drivers/vx/vx_core.c # 2005/01/24 07:56:51+01:00 perex@suse.cz +3 -5 # [ALSA] replace schedule_timeout() with msleep() # # D:2005/01/24 14:56:51 # C:Digigram VX core # F:drivers/vx/vx_core.c:1.13->1.14 # L:Use msleep() instead of schedule_timeout() to guarantee the task # L:delays as expected. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:39:04+01:00 perex@suse.cz # [ALSA] replace schedule_timeout() with msleep() # # RawMidi Midlevel # Use msleep instead of schedule_timeout() to guarantee the task delays # as expected. This also removes a dependence on the value of HZ. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # sound/core/rawmidi.c # 2005/01/24 07:55:43+01:00 perex@suse.cz +3 -4 # [ALSA] replace schedule_timeout() with msleep() # # D:2005/01/24 14:55:43 # C:RawMidi Midlevel # F:core/rawmidi.c:1.52->1.53 # L:Use msleep instead of schedule_timeout() to guarantee the task delays # L:as expected. This also removes a dependence on the value of HZ. # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:37:18+01:00 perex@suse.cz # [ALSA] Special AC97 patch for ASUS W1000/CMI9739 laptop # # AC97 Codec # This patch fixes sound output on the ASUS W1000 laptop with the CMI9739 # chip. It wrongly reports that it has a SPDIF in, when in fact we wish to # use the EAPD pin. # # Signed-off-by: James Courtier-Dutton # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.c # 2005/01/24 05:11:00+01:00 perex@suse.cz +9 -0 # [ALSA] Special AC97 patch for ASUS W1000/CMI9739 laptop # # D:2005/01/24 12:11:00 # C:AC97 Codec # F:pci/ac97/ac97_patch.c:1.70->1.71 # L:This patch fixes sound output on the ASUS W1000 laptop with the CMI9739 # L:chip. It wrongly reports that it has a SPDIF in, when in fact we wish to # L:use the EAPD pin. # Signed-off-by: James Courtier-Dutton # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/25 20:35:33+01:00 perex@suse.cz # [ALSA] Warning doc about VIA82xx recording # # Documentation # Add warning about the consequences of adjusting the 'Input Source Select' # of VIA82xx. # # Signed-off-by: Ross Kendall Axe # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/VIA82xx-mixer.txt # 2005/01/25 14:32:28+01:00 perex@suse.cz +8 -0 # [ALSA] Warning doc about VIA82xx recording # # D:2005/01/21 19:33:11 # C:Documentation # F:Documentation/VIA82xx-mixer.txt:INITIAL->1.1 # L:Add warning about the consequences of adjusting the 'Input Source Select' # L:of VIA82xx. # Signed-off-by: Ross Kendall Axe # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/VIA82xx-mixer.txt # 2005/01/25 14:32:28+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/Documentation/sound/alsa/VIA82xx-mixer.txt # # ChangeSet # 2005/01/25 20:33:42+01:00 perex@suse.cz # [ALSA] fix usage of preprocessor directive inside macro # # HDA Intel driver # gcc-2 complains about preprocessor directives inside a macro argument list # # Signed-off-by: Clemens Ladisch # # sound/pci/hda/hda_intel.c # 2005/01/21 10:46:00+01:00 perex@suse.cz +3 -3 # [ALSA] fix usage of preprocessor directive inside macro # # D:2005/01/21 17:46:00 # C:HDA Intel driver # F:pci/hda/hda_intel.c:1.1->1.2 # L:gcc-2 complains about preprocessor directives inside a macro argument list # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/01/25 20:32:04+01:00 perex@suse.cz # [ALSA] add more Yamaha USB MIDI quirks # # USB generic driver # add support for Yamaha UC-MX, UC-KX, CLP-175, SPX2000 # # Signed-off-by: Clemens Ladisch # # sound/usb/usbquirks.h # 2005/01/21 01:32:12+01:00 perex@suse.cz +6 -0 # [ALSA] add more Yamaha USB MIDI quirks # # D:2005/01/21 08:32:12 # C:USB generic driver # F:usb/usbquirks.h:1.39->1.40 # L:add support for Yamaha UC-MX, UC-KX, CLP-175, SPX2000 # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/01/20 22:29:20+01:00 perex@suse.cz # [ALSA] remove obsolete sound/core/ioctl32 directory # # The compatibility layer is integrated to ALSA midlevel code now. # # include/sound/version.h~ # 2005/01/20 22:26:24+01:00 perex@suse.cz +3 -0 # # include/sound/version.h~ # 2005/01/20 22:26:24+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/include/sound/version.h~ # # BitKeeper/deleted/.del-hwdep32.c~2628af71433fb282 # 2005/01/20 22:14:14+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/hwdep32.c # # BitKeeper/deleted/.del-ioctl32.h~6fa31b659e702cbd # 2005/01/20 22:14:12+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/ioctl32.h # # BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f # 2005/01/20 22:14:11+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/ioctl32.c # # BitKeeper/deleted/.del-Makefile~767d5bad6308fa6d # 2005/01/20 22:14:08+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/Makefile # # BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8 # 2005/01/20 22:14:05+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/pcm32.c # # BitKeeper/deleted/.del-rawmidi32.c~b24d28b2a36477f1 # 2005/01/20 22:14:03+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/rawmidi32.c # # BitKeeper/deleted/.del-seq32.c~c96c6dffe1307ca0 # 2005/01/20 22:14:00+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/seq32.c # # BitKeeper/deleted/.del-timer32.c~e0c2522dbc4e6d68 # 2005/01/20 22:13:55+01:00 perex@suse.cz +0 -0 # Delete: sound/core/ioctl32/timer32.c # # ChangeSet # 2005/01/20 21:47:16+01:00 perex@suse.cz # Merge suse.cz:/home/perex/bk/linux-sound/linux-sound # into suse.cz:/home/perex/bk/linux-sound/work # # sound/pci/Kconfig # 2005/01/20 21:46:53+01:00 perex@suse.cz +0 -0 # Auto merged # # ChangeSet # 2005/01/20 20:33:37+01:00 perex@suse.cz # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # ALSA<-OSS sequencer # Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # macros. # # Signed-off-by: Takashi Iwai # # sound/core/timer.c # 2005/01/20 10:42:36+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_queue.c # 2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_clientmgr.c # 2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/seq/oss/seq_oss_synth.c # 2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/seq/oss/seq_oss_midi.c # 2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/pcm_native.c # 2005/01/20 10:42:36+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/memory.c # 2005/01/20 10:42:36+01:00 perex@suse.cz +2 -2 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # sound/core/init.c # 2005/01/20 10:42:36+01:00 perex@suse.cz +1 -1 # [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros # # D:2005/01/20 17:42:36 # C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer # C:ALSA<-OSS sequencer # F:core/init.c:1.54->1.55 # F:core/memory.c:1.36->1.37 # F:core/pcm_native.c:1.112->1.113 # F:core/timer.c:1.64->1.65 # F:core/seq/seq_clientmgr.c:1.41->1.42 # F:core/seq/seq_queue.c:1.15->1.16 # F:core/seq/oss/seq_oss_midi.c:1.16->1.17 # F:core/seq/oss/seq_oss_synth.c:1.16->1.17 # L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK() # L:macros. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:32:02+01:00 perex@suse.cz # [ALSA] Remove snd-ioctl32 entry # # ALSA Core # Remove the entry for snd-ioctl32. The 32bit wrapper is built in the core # module. # # Signed-off-by: Takashi Iwai # # sound/core/Makefile # 2005/01/20 10:16:39+01:00 perex@suse.cz +0 -1 # [ALSA] Remove snd-ioctl32 entry # # D:2005/01/20 17:16:35 # C:ALSA Core # F:core/Kconfig:1.7->1.8 # F:core/Makefile:1.54->1.55 # L:Remove the entry for snd-ioctl32. The 32bit wrapper is built in the core # L:module. # Signed-off-by: Takashi Iwai # # sound/core/Kconfig # 2005/01/20 10:16:35+01:00 perex@suse.cz +0 -14 # [ALSA] Remove snd-ioctl32 entry # # D:2005/01/20 17:16:35 # C:ALSA Core # F:core/Kconfig:1.7->1.8 # F:core/Makefile:1.54->1.55 # L:Remove the entry for snd-ioctl32. The 32bit wrapper is built in the core # L:module. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:30:46+01:00 perex@suse.cz # [ALSA] Export new register/unregister functions # # ALSA Core # Export new register/unregister functions for compat control-ioctls. # # Signed-off-by: Takashi Iwai # # sound/core/sound.c # 2005/01/20 10:15:37+01:00 perex@suse.cz +4 -0 # [ALSA] Export new register/unregister functions # # D:2005/01/20 17:15:37 # C:ALSA Core # F:core/sound.c:1.71->1.72 # L:Export new register/unregister functions for compat control-ioctls. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:29:26+01:00 perex@suse.cz # [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers # # ALSA<-OSS emulation,ALSA<-OSS sequencer # The ioctl handlers for OSS compatible drivers are rewritten using # unlocked/compat_ioctl. # # Signed-off-by: Takashi Iwai # # sound/core/seq/oss/seq_oss.c # 2005/01/20 10:14:45+01:00 perex@suse.cz +11 -10 # [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers # # D:2005/01/20 17:14:44 # C:ALSA<-OSS emulation,ALSA<-OSS sequencer # F:core/oss/mixer_oss.c:1.37->1.38 # F:core/oss/pcm_oss.c:1.83->1.84 # F:core/seq/oss/seq_oss.c:1.17->1.18 # L:The ioctl handlers for OSS compatible drivers are rewritten using # L:unlocked/compat_ioctl. # Signed-off-by: Takashi Iwai # # sound/core/oss/pcm_oss.c # 2005/01/20 10:14:45+01:00 perex@suse.cz +9 -13 # [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers # # D:2005/01/20 17:14:44 # C:ALSA<-OSS emulation,ALSA<-OSS sequencer # F:core/oss/mixer_oss.c:1.37->1.38 # F:core/oss/pcm_oss.c:1.83->1.84 # F:core/seq/oss/seq_oss.c:1.17->1.18 # L:The ioctl handlers for OSS compatible drivers are rewritten using # L:unlocked/compat_ioctl. # Signed-off-by: Takashi Iwai # # sound/core/oss/mixer_oss.c # 2005/01/20 10:14:44+01:00 perex@suse.cz +11 -10 # [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers # # D:2005/01/20 17:14:44 # C:ALSA<-OSS emulation,ALSA<-OSS sequencer # F:core/oss/mixer_oss.c:1.37->1.38 # F:core/oss/pcm_oss.c:1.83->1.84 # F:core/seq/oss/seq_oss.c:1.17->1.18 # L:The ioctl handlers for OSS compatible drivers are rewritten using # L:unlocked/compat_ioctl. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:28:06+01:00 perex@suse.cz # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # using unlocked/compat_ioctl. # The 32bit wrapper is merged to the core module. # # Signed-off-by: Takashi Iwai # # sound/core/timer_compat.c # 2005/01/20 19:16:31+01:00 perex@suse.cz +119 -0 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_compat.c # 2005/01/20 19:17:01+01:00 perex@suse.cz +137 -0 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/rawmidi_compat.c # 2005/01/20 19:16:21+01:00 perex@suse.cz +120 -0 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/timer_compat.c # 2005/01/20 19:16:31+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/core/timer_compat.c # # sound/core/timer.c # 2005/01/20 10:13:40+01:00 perex@suse.cz +9 -14 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/seq/seq_compat.c # 2005/01/20 19:17:01+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/core/seq/seq_compat.c # # sound/core/seq/seq_clientmgr.c # 2005/01/20 10:13:41+01:00 perex@suse.cz +9 -9 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/rawmidi_compat.c # 2005/01/20 19:16:21+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/core/rawmidi_compat.c # # sound/core/rawmidi.c # 2005/01/20 10:13:40+01:00 perex@suse.cz +13 -14 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/hwdep.c # 2005/01/20 10:13:40+01:00 perex@suse.cz +11 -14 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # include/sound/hwdep.h # 2005/01/20 10:13:41+01:00 perex@suse.cz +1 -0 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/hwdep_compat.c # 2005/01/20 19:16:12+01:00 perex@suse.cz +77 -0 # [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API # # D:2005/01/20 17:13:40 # C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer # F:core/hwdep.c:1.28->1.29 # F:core/hwdep_compat.c:INITIAL->1.1 # F:core/rawmidi.c:1.51->1.52 # F:core/rawmidi_compat.c:INITIAL->1.1 # F:core/timer.c:1.63->1.64 # F:core/timer_compat.c:INITIAL->1.1 # F:core/seq/seq_clientmgr.c:1.40->1.41 # F:core/seq/seq_compat.c:INITIAL->1.1 # F:include/hwdep.h:1.6->1.7 # L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten # L:using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/hwdep_compat.c # 2005/01/20 19:16:12+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/core/hwdep_compat.c # # ChangeSet # 2005/01/20 20:26:43+01:00 perex@suse.cz # [ALSA] unlocked/compat_ioctl rewrite for PCM API # # PCM Midlevel # The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl. # The 32bit wrapper is merged to the core module. # # Signed-off-by: Takashi Iwai # # sound/core/pcm_native.c # 2005/01/20 10:11:46+01:00 perex@suse.cz +17 -18 # [ALSA] unlocked/compat_ioctl rewrite for PCM API # # D:2005/01/20 17:11:46 # C:PCM Midlevel # F:core/pcm.c:1.49->1.50 # F:core/pcm_compat.c:INITIAL->1.1 # F:core/pcm_native.c:1.111->1.112 # L:The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/pcm.c # 2005/01/20 10:11:46+01:00 perex@suse.cz +2 -0 # [ALSA] unlocked/compat_ioctl rewrite for PCM API # # D:2005/01/20 17:11:46 # C:PCM Midlevel # F:core/pcm.c:1.49->1.50 # F:core/pcm_compat.c:INITIAL->1.1 # F:core/pcm_native.c:1.111->1.112 # L:The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/pcm_compat.c # 2005/01/20 19:15:57+01:00 perex@suse.cz +513 -0 # [ALSA] unlocked/compat_ioctl rewrite for PCM API # # D:2005/01/20 17:11:46 # C:PCM Midlevel # F:core/pcm.c:1.49->1.50 # F:core/pcm_compat.c:INITIAL->1.1 # F:core/pcm_native.c:1.111->1.112 # L:The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # Signed-off-by: Takashi Iwai # # sound/core/pcm_compat.c # 2005/01/20 19:15:57+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/core/pcm_compat.c # # ChangeSet # 2005/01/20 20:25:19+01:00 perex@suse.cz # [ALSA] unlocked/compat_ioctl rewrite for control API # # Control Midlevel # ioctl handler for control API is rewritten using unlocked/compat_ioctl. # The 32bit wrapper is merged to the core module. # # Added a new register/unregister function for compat control ioctls. # # Signed-off-by: Takashi Iwai # # sound/core/control.c # 2005/01/20 10:10:23+01:00 perex@suse.cz +95 -81 # [ALSA] unlocked/compat_ioctl rewrite for control API # # D:2005/01/20 17:10:23 # C:Control Midlevel # F:core/control.c:1.55->1.56 # F:core/control_compat.c:INITIAL->1.1 # F:include/control.h:1.11->1.12 # L:ioctl handler for control API is rewritten using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # L: # L:Added a new register/unregister function for compat control ioctls. # Signed-off-by: Takashi Iwai # # include/sound/control.h # 2005/01/20 10:10:24+01:00 perex@suse.cz +7 -0 # [ALSA] unlocked/compat_ioctl rewrite for control API # # D:2005/01/20 17:10:23 # C:Control Midlevel # F:core/control.c:1.55->1.56 # F:core/control_compat.c:INITIAL->1.1 # F:include/control.h:1.11->1.12 # L:ioctl handler for control API is rewritten using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # L: # L:Added a new register/unregister function for compat control ioctls. # Signed-off-by: Takashi Iwai # # sound/core/control_compat.c # 2005/01/20 19:15:43+01:00 perex@suse.cz +412 -0 # [ALSA] unlocked/compat_ioctl rewrite for control API # # D:2005/01/20 17:10:23 # C:Control Midlevel # F:core/control.c:1.55->1.56 # F:core/control_compat.c:INITIAL->1.1 # F:include/control.h:1.11->1.12 # L:ioctl handler for control API is rewritten using unlocked/compat_ioctl. # L:The 32bit wrapper is merged to the core module. # L: # L:Added a new register/unregister function for compat control ioctls. # Signed-off-by: Takashi Iwai # # sound/core/control_compat.c # 2005/01/20 19:15:43+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/core/control_compat.c # # ChangeSet # 2005/01/20 20:23:54+01:00 perex@suse.cz # [ALSA] Add Intel HDA driver # # Documentation,PCI drivers,HDA generic driver,HDA Codec driver # HDA Intel driver # Added a new Intel High-Definition audio driver. # The driver consists of two separate modules: the generic support # module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # chipset (snd-hda-intel). The snd-hda-intel was called formerly # snd-azx in the ALSA 1.0.8 rlease. # # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_realtek.c # 2005/01/20 19:15:31+01:00 perex@suse.cz +1174 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_cmedia.c # 2005/01/20 19:15:26+01:00 perex@suse.cz +614 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_proc.c # 2005/01/20 19:15:21+01:00 perex@suse.cz +298 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_patch.h # 2005/01/20 19:15:17+01:00 perex@suse.cz +14 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_local.h # 2005/01/20 19:15:12+01:00 perex@suse.cz +159 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_intel.c # 2005/01/20 19:15:07+01:00 perex@suse.cz +1449 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_generic.c # 2005/01/20 19:15:01+01:00 perex@suse.cz +898 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.h # 2005/01/20 19:14:56+01:00 perex@suse.cz +602 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/hda_codec.c # 2005/01/20 19:14:51+01:00 perex@suse.cz +1731 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/Makefile # 2005/01/20 19:14:46+01:00 perex@suse.cz +7 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/hda/patch_realtek.c # 2005/01/20 19:15:31+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/patch_realtek.c # # sound/pci/hda/patch_cmedia.c # 2005/01/20 19:15:26+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/patch_cmedia.c # # sound/pci/hda/hda_proc.c # 2005/01/20 19:15:21+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_proc.c # # sound/pci/hda/hda_patch.h # 2005/01/20 19:15:17+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_patch.h # # sound/pci/hda/hda_local.h # 2005/01/20 19:15:12+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_local.h # # sound/pci/hda/hda_intel.c # 2005/01/20 19:15:07+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_intel.c # # sound/pci/hda/hda_generic.c # 2005/01/20 19:15:01+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_generic.c # # sound/pci/hda/hda_codec.h # 2005/01/20 19:14:56+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_codec.h # # sound/pci/hda/hda_codec.c # 2005/01/20 19:14:51+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_codec.c # # sound/pci/hda/Makefile # 2005/01/20 19:14:46+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/Makefile # # sound/pci/Makefile # 2005/01/20 08:02:28+01:00 perex@suse.cz +1 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # sound/pci/Kconfig # 2005/01/20 08:02:28+01:00 perex@suse.cz +11 -1 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/01/20 08:02:27+01:00 perex@suse.cz +31 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/hda_codec.txt # 2005/01/20 19:14:31+01:00 perex@suse.cz +299 -0 # [ALSA] Add Intel HDA driver # # D:2005/01/20 15:02:27 # C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver # C:HDA Intel driver # F:Documentation/ALSA-Configuration.txt:1.63->1.64 # F:Documentation/hda_codec.txt:INITIAL->1.1 # F:pci/Kconfig:1.39->1.40 # F:pci/Makefile:1.19->1.20 # F:pci/hda/Makefile:INITIAL->1.1 # F:pci/hda/hda_codec.c:INITIAL->1.1 # F:pci/hda/hda_codec.h:INITIAL->1.1 # F:pci/hda/hda_generic.c:INITIAL->1.1 # F:pci/hda/hda_intel.c:INITIAL->1.1 # F:pci/hda/hda_local.h:INITIAL->1.1 # F:pci/hda/hda_patch.h:INITIAL->1.1 # F:pci/hda/hda_proc.c:INITIAL->1.1 # F:pci/hda/patch_cmedia.c:INITIAL->1.1 # F:pci/hda/patch_realtek.c:INITIAL->1.1 # L:Added a new Intel High-Definition audio driver. # L:The driver consists of two separate modules: the generic support # L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7 # L:chipset (snd-hda-intel). The snd-hda-intel was called formerly # L:snd-azx in the ALSA 1.0.8 rlease. # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/hda_codec.txt # 2005/01/20 19:14:31+01:00 perex@suse.cz +0 -0 # BitKeeper file /home/perex/bk/linux-sound/work/Documentation/sound/alsa/hda_codec.txt # # ChangeSet # 2005/01/20 20:22:29+01:00 perex@suse.cz # [ALSA] Enable HP jack sense for FSC Scenic-W # # AC97 Codec # Enable 'Headphone Jack Sense' control on FSC Scenic-W as default, too. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.c # 2005/01/20 04:43:19+01:00 perex@suse.cz +1 -0 # [ALSA] Enable HP jack sense for FSC Scenic-W # # D:2005/01/20 11:43:19 # C:AC97 Codec # F:pci/ac97/ac97_patch.c:1.69->1.70 # L:Enable 'Headphone Jack Sense' control on FSC Scenic-W as default, too. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:21:09+01:00 perex@suse.cz # [ALSA] Add quirk for HP nc8000 # # Intel8x0 driver # Added ac97 quirk for HP nc8000. # The list is sorted again. # # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0.c # 2005/01/20 04:41:50+01:00 perex@suse.cz +10 -4 # [ALSA] Add quirk for HP nc8000 # # D:2005/01/20 11:41:50 # C:Intel8x0 driver # F:pci/intel8x0.c:1.189->1.190 # L:Added ac97 quirk for HP nc8000. # L:The list is sorted again. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:19:48+01:00 perex@suse.cz # [ALSA] Add quirk for HP pavilion ZV5030US # # ATIIXP driver # Added ac97 quirk for HP Pavilion ZV5030US to bind the control with # mute-LED. # # Signed-off-by: Takashi Iwai # # sound/pci/atiixp.c # 2005/01/19 09:43:06+01:00 perex@suse.cz +6 -0 # [ALSA] Add quirk for HP pavilion ZV5030US # # D:2005/01/19 16:43:06 # C:ATIIXP driver # F:pci/atiixp.c:1.30->1.31 # L:Added ac97 quirk for HP Pavilion ZV5030US to bind the control with # L:mute-LED. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:18:30+01:00 perex@suse.cz # [ALSA] Simplify the general ac97 volume/switch callback # # AC97 Codec # Simplified the control callbacks of general AC97 volumes/switches. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_local.h # 2005/01/19 05:03:51+01:00 perex@suse.cz +2 -4 # [ALSA] Simplify the general ac97 volume/switch callback # # D:2005/01/19 12:03:49 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.168->1.169 # F:pci/ac97/ac97_local.h:1.11->1.12 # L:Simplified the control callbacks of general AC97 volumes/switches. # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_codec.c # 2005/01/19 05:03:49+01:00 perex@suse.cz +36 -37 # [ALSA] Simplify the general ac97 volume/switch callback # # D:2005/01/19 12:03:49 # C:AC97 Codec # F:pci/ac97/ac97_codec.c:1.168->1.169 # F:pci/ac97/ac97_local.h:1.11->1.12 # L:Simplified the control callbacks of general AC97 volumes/switches. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:17:15+01:00 perex@suse.cz # [ALSA] Add missing inclusion of linux/device.h # # Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver # Added the missing inclusion of # # Signed-off-by: Takashi Iwai # # sound/pcmcia/vx/vxp_ops.c # 2005/01/19 04:36:30+01:00 perex@suse.cz +1 -0 # [ALSA] Add missing inclusion of linux/device.h # # D:2005/01/19 11:36:29 # C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver # F:drivers/vx/vx_core.c:1.12->1.13 # F:drivers/vx/vx_hwdep.c:1.4->1.5 # F:pci/vx222/vx222_ops.c:1.8->1.9 # F:pcmcia/vx/vxp_ops.c:1.5->1.6 # L:Added the missing inclusion of # Signed-off-by: Takashi Iwai # # sound/pci/vx222/vx222_ops.c # 2005/01/19 04:36:30+01:00 perex@suse.cz +1 -0 # [ALSA] Add missing inclusion of linux/device.h # # D:2005/01/19 11:36:29 # C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver # F:drivers/vx/vx_core.c:1.12->1.13 # F:drivers/vx/vx_hwdep.c:1.4->1.5 # F:pci/vx222/vx222_ops.c:1.8->1.9 # F:pcmcia/vx/vxp_ops.c:1.5->1.6 # L:Added the missing inclusion of # Signed-off-by: Takashi Iwai # # sound/drivers/vx/vx_hwdep.c # 2005/01/19 04:36:29+01:00 perex@suse.cz +1 -0 # [ALSA] Add missing inclusion of linux/device.h # # D:2005/01/19 11:36:29 # C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver # F:drivers/vx/vx_core.c:1.12->1.13 # F:drivers/vx/vx_hwdep.c:1.4->1.5 # F:pci/vx222/vx222_ops.c:1.8->1.9 # F:pcmcia/vx/vxp_ops.c:1.5->1.6 # L:Added the missing inclusion of # Signed-off-by: Takashi Iwai # # sound/drivers/vx/vx_core.c # 2005/01/19 04:36:29+01:00 perex@suse.cz +1 -0 # [ALSA] Add missing inclusion of linux/device.h # # D:2005/01/19 11:36:29 # C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver # F:drivers/vx/vx_core.c:1.12->1.13 # F:drivers/vx/vx_hwdep.c:1.4->1.5 # F:pci/vx222/vx222_ops.c:1.8->1.9 # F:pcmcia/vx/vxp_ops.c:1.5->1.6 # L:Added the missing inclusion of # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:15:52+01:00 perex@suse.cz # [ALSA] Add workaround for buggy ATI IXP hardwares # # ATIIXP-modem driver # Added a workaround for buggy ATI IXP hardwares which returns # bogus DMA pointer register value. # # Signed-off-by: Takashi Iwai # # sound/pci/atiixp_modem.c # 2005/01/19 04:35:04+01:00 perex@suse.cz +11 -12 # [ALSA] Add workaround for buggy ATI IXP hardwares # # D:2005/01/19 11:35:04 # C:ATIIXP-modem driver # F:pci/atiixp_modem.c:1.12->1.13 # L:Added a workaround for buggy ATI IXP hardwares which returns # L:bogus DMA pointer register value. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:14:34+01:00 perex@suse.cz # [ALSA] Add support for Chaintech 9CJS # # ICE1712 driver # Added the support for Chaintech 9CJS by Delmaire Maxime. # # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/vt1720_mobo.h # 2005/01/19 04:32:46+01:00 perex@suse.cz +3 -1 # [ALSA] Add support for Chaintech 9CJS # # D:2005/01/19 11:32:46 # C:ICE1712 driver # F:pci/ice1712/vt1720_mobo.c:1.2->1.3 # F:pci/ice1712/vt1720_mobo.h:1.2->1.3 # L:Added the support for Chaintech 9CJS by Delmaire Maxime. # Signed-off-by: Takashi Iwai # # sound/pci/ice1712/vt1720_mobo.c # 2005/01/19 04:32:46+01:00 perex@suse.cz +9 -0 # [ALSA] Add support for Chaintech 9CJS # # D:2005/01/19 11:32:46 # C:ICE1712 driver # F:pci/ice1712/vt1720_mobo.c:1.2->1.3 # F:pci/ice1712/vt1720_mobo.h:1.2->1.3 # L:Added the support for Chaintech 9CJS by Delmaire Maxime. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:13:15+01:00 perex@suse.cz # [ALSA] AK4117 code - fixed cosmetic typos # # AK4117 receiver # # # Signed-off-by: Jaroslav Kysela # # include/sound/ak4117.h # 2005/01/18 08:41:15+01:00 perex@suse.cz +3 -3 # [ALSA] AK4117 code - fixed cosmetic typos # # D:2005/01/18 15:41:15 # C:AK4117 receiver # F:include/ak4117.h:1.1->1.2 # L: # Signed-off-by: Jaroslav Kysela # # ChangeSet # 2005/01/20 20:11:59+01:00 perex@suse.cz # [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio # # USB generic driver # Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality # of interfaces 3-5 and cause errors when used with those. Add a quirk to # tell the driver not to use them. # # Signed-off-by: Clemens Ladisch # # sound/usb/usbquirks.h # 2005/01/17 10:41:38+01:00 perex@suse.cz +70 -5 # [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio # # D:2005/01/17 17:41:34 # C:USB generic driver # F:usb/usbaudio.c:1.113->1.114 # F:usb/usbaudio.h:1.35->1.36 # F:usb/usbquirks.h:1.38->1.39 # L:Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality # L:of interfaces 3-5 and cause errors when used with those. Add a quirk to # L:tell the driver not to use them. # Signed-off-by: Clemens Ladisch # # sound/usb/usbaudio.h # 2005/01/17 10:41:38+01:00 perex@suse.cz +3 -0 # [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio # # D:2005/01/17 17:41:34 # C:USB generic driver # F:usb/usbaudio.c:1.113->1.114 # F:usb/usbaudio.h:1.35->1.36 # F:usb/usbquirks.h:1.38->1.39 # L:Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality # L:of interfaces 3-5 and cause errors when used with those. Add a quirk to # L:tell the driver not to use them. # Signed-off-by: Clemens Ladisch # # sound/usb/usbaudio.c # 2005/01/17 10:41:34+01:00 perex@suse.cz +2 -0 # [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio # # D:2005/01/17 17:41:34 # C:USB generic driver # F:usb/usbaudio.c:1.113->1.114 # F:usb/usbaudio.h:1.35->1.36 # F:usb/usbquirks.h:1.38->1.39 # L:Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality # L:of interfaces 3-5 and cause errors when used with those. Add a quirk to # L:tell the driver not to use them. # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/01/20 20:10:41+01:00 perex@suse.cz # [ALSA] Fix silent output on some machines with AD1981x codecs # # AC97 Codec # Fixed the default state of 'Headphone Jack Sense' switch on AD1981x # codecs. Setting this on affects the output of some machines (e.g. # Thindpads). # # The default value is set on only hardwares which are known to work. # # Signed-off-by: Takashi Iwai # # sound/pci/ac97/ac97_patch.c # 2005/01/17 06:47:20+01:00 perex@suse.cz +14 -2 # [ALSA] Fix silent output on some machines with AD1981x codecs # # D:2005/01/17 13:47:20 # C:AC97 Codec # F:pci/ac97/ac97_patch.c:1.68->1.69 # L:Fixed the default state of 'Headphone Jack Sense' switch on AD1981x # L:codecs. Setting this on affects the output of some machines (e.g. # L:Thindpads). # L: # L:The default value is set on only hardwares which are known to work. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:09:28+01:00 perex@suse.cz # [ALSA] AC'97 Audio support for Intel ICH7 # # Intel8x0 driver # This patch adds the ICH7 AC'97 DID the the intel8x0.c AC'97 audio # driver. This patch was build against 2.6.11-rc1. # # Signed-off-by: Jason Gaston # Signed-off-by: Takashi Iwai # # sound/pci/intel8x0.c # 2005/01/17 04:29:18+01:00 perex@suse.cz +6 -0 # [ALSA] AC'97 Audio support for Intel ICH7 # # D:2005/01/17 11:29:18 # C:Intel8x0 driver # F:pci/intel8x0.c:1.188->1.189 # L:This patch adds the ICH7 AC'97 DID the the intel8x0.c AC'97 audio # L:driver. This patch was build against 2.6.11-rc1. # Signed-off-by: Jason Gaston # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:08:09+01:00 perex@suse.cz # [ALSA] Fix compilation on big-endian arch # # RME HDSP driver # Fixed typo in the code for big-endian architectures. # # Signed-off-by: Takashi Iwai # # sound/pci/rme9652/hdsp.c # 2005/01/14 12:52:06+01:00 perex@suse.cz +1 -1 # [ALSA] Fix compilation on big-endian arch # # D:2005/01/14 19:52:06 # C:RME HDSP driver # F:pci/rme9652/hdsp.c:1.78->1.79 # L:Fixed typo in the code for big-endian architectures. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:07:01+01:00 perex@suse.cz # [ALSA] Show firmware loading state in proc file # # Digigram VX core # Show the firmware loading state in proc file. # # Signed-off-by: Takashi Iwai # # sound/drivers/vx/vx_core.c # 2005/01/14 10:41:36+01:00 perex@suse.cz +4 -0 # [ALSA] Show firmware loading state in proc file # # D:2005/01/14 17:41:36 # C:Digigram VX core # F:drivers/vx/vx_core.c:1.11->1.12 # L:Show the firmware loading state in proc file. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:05:33+01:00 perex@suse.cz # [ALSA] Fix struct size mismatch # # IOCTL32 emulation # Fixed the struct size mismatch - should work on SPARC64 now, too. # # Signed-off-by: Takashi Iwai # # sound/core/ioctl32/ioctl32.c # 2005/01/14 04:15:16+01:00 perex@suse.cz +1 -1 # [ALSA] Fix struct size mismatch # # D:2005/01/14 11:15:16 # C:IOCTL32 emulation # F:core/ioctl32/ioctl32.c:1.28->1.29 # L:Fixed the struct size mismatch - should work on SPARC64 now, too. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:04:23+01:00 perex@suse.cz # [ALSA] Add missing FORWARD ioctl # # IOCTL32 emulation # Added the missing FORWARD ioctl. # # Signed-off-by: Takashi Iwai # # sound/core/ioctl32/pcm32.c # 2005/01/14 03:51:12+01:00 perex@suse.cz +3 -0 # [ALSA] Add missing FORWARD ioctl # # D:2005/01/14 10:51:12 # C:IOCTL32 emulation # F:core/ioctl32/pcm32.c:1.23->1.24 # L:Added the missing FORWARD ioctl. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:03:02+01:00 perex@suse.cz # [ALSA] Fix struct alignment on PPC64 # # IOCTL32 emulation # Fixed the struct size mismatch (due to alignment) of # snd_ctl_elem_value_t for PPC64. # # Signed-off-by: Takashi Iwai # # sound/core/ioctl32/ioctl32.c # 2005/01/14 03:50:29+01:00 perex@suse.cz +3 -0 # [ALSA] Fix struct alignment on PPC64 # # D:2005/01/14 10:50:29 # C:IOCTL32 emulation # F:core/ioctl32/ioctl32.c:1.27->1.28 # L:Fixed the struct size mismatch (due to alignment) of # L:snd_ctl_elem_value_t for PPC64. # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 20:01:42+01:00 perex@suse.cz # [ALSA] fix typo # # Documentation # # # Signed-off-by: Clemens Ladisch # # Documentation/sound/alsa/ALSA-Configuration.txt # 2005/01/14 03:15:32+01:00 perex@suse.cz +1 -1 # [ALSA] fix typo # # D:2005/01/14 10:15:32 # C:Documentation # F:Documentation/ALSA-Configuration.txt:1.62->1.63 # L: # Signed-off-by: Clemens Ladisch # # ChangeSet # 2005/01/20 20:00:22+01:00 perex@suse.cz # [ALSA] Fix typos in doc # # Documentation # Fixed typos in the document by Kirill Smelkov # # Signed-off-by: Takashi Iwai # # Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl # 2005/01/13 10:29:03+01:00 perex@suse.cz +16 -13 # [ALSA] Fix typos in doc # # D:2005/01/13 17:29:03 # C:Documentation # F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.46->1.47 # L:Fixed typos in the document by Kirill Smelkov # Signed-off-by: Takashi Iwai # # ChangeSet # 2005/01/20 19:58:45+01:00 perex@suse.cz # ALSA CVS update # PCM Midlevel # Sumary: Fix comment of snd_pcm_lib_malloc_pages() # # Fixed comment of snd_pcm_lib_malloc_pages() by # Kirill Smelkov . # # Signed-off-by: Takashi Iwai # # sound/core/pcm_memory.c # 2005/01/13 10:27:29+01:00 perex@suse.cz +1 -1 # ALSA CVS update # D:2005/01/13 17:27:29 # C:PCM Midlevel # F:core/pcm_memory.c:1.33->1.34 # L:Sumary: Fix comment of snd_pcm_lib_malloc_pages() # L: # L:Fixed comment of snd_pcm_lib_malloc_pages() by # L:Kirill Smelkov . # Signed-off-by: Takashi Iwai # diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt --- a/Documentation/sound/alsa/ALSA-Configuration.txt 2005-03-03 21:43:47 -08:00 +++ b/Documentation/sound/alsa/ALSA-Configuration.txt 2005-03-03 21:43:47 -08:00 @@ -7,75 +7,75 @@ Kernel Configuration ==================== -To enable the ALSA support, at least you need to build the kernel with -the primary sound card support (CONFIG_SOUND). Since ALSA can emulate -the OSS, you don't have to choose any of the OSS/Free modules. Please -enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and -PCM supports if you want to run the OSS application with the ALSA. +To enable ALSA support you need at least to build the kernel with +primary sound card support (CONFIG_SOUND). Since ALSA can emulate OSS, +you don't have to choose any of the OSS modules. -When you want to support the WaveTable functionality on some cards -such like SB Live!, you need to enable "Sequencer support" +Enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and +PCM supports if you want to run OSS applications with ALSA. + +If you want to support the WaveTable functionality on cards such as +SB Live! then you need to enable "Sequencer support" (CONFIG_SND_SEQUENCER). -For getting more verbose debug messages, turn on "Verbose printk" and -"Debug" options. For checking the memory leaks, you can turn on -"Debug memory" option, too. "Debug detection" will put more -additional checks for the detection of cards. - -Please note that all the ALSA ISA drivers support Linux isapnp API (if -the card supports). You don't need to configure the PnP via -isapnptools. +To make ALSA debug messages more verbose, enable the "Verbose printk" +and "Debug" options. To check for memory leaks, turn on "Debug memory" +too. "Debug detection" will add checks for the detection of cards. + +Please note that all the ALSA ISA drivers support the Linux isapnp API +(if the card supports ISA PnP). You don't need to configure the cards +using isapnptools. Creating ALSA devices ===================== -Use the /dev/MAKEDEV script to create the nessecary device nodes. +This depends on your distribution, but normally you use the /dev/MAKEDEV +script to create the necessary device nodes. On some systems you use a +script named 'snddevices'. Module parameters ================= - A user can modify or set parameters at the load time of the module. If - the module supports more cards and you have got more than one card - of the same type, you may simply specify more values for the parameter, - delimited by commas. - - Note that module option names were changed in 0.9.0rc4. The 'snd_' - prefix was removed. +The user can load modules with options. If the module supports more than +one card and you have more than one card of the same type then you can +specify multiple values for the option separated by commas. + +Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd ---------- - The module snd is the ALSA core module, which is used by all ALSA - card drivers. This takes the global options for creating devices, - etc. + The core ALSA module. It is used by all ALSA card drivers. + It takes the following options which have global effects. - major - major # for sound driver - - default is 116 + major - major number for sound driver + - Default: 116 cards_limit - - specifies card limit # for auto-loading (1-8) - - default is 1 - - for auto-loading more than 1 card, specify this option - together with snd-card-X aliases. + - limiting card index for auto-loading (1-8) + - Default: 1 + - For auto-loading more than one card, specify this + option together with snd-card-X aliases. device_mode - - specifies permission mask for dynamic sound device filesystem - (available only when DEVFS is enabled) - - default value = 0666 - - for example 'device_mode=0660' + - permission mask for dynamic sound device filesystem + - This is available only when DEVFS is enabled + - Default: 0666 + - E.g.: device_mode=0660 Module snd-pcm-oss ------------------ The PCM OSS emulation module. - This module takes the options to change the mapping of devices. + This module takes options which change the mapping of devices. dsp_map - PCM device number maps assigned to the 1st OSS device. - (default: 0) + - Default: 0 adsp_map - PCM device number maps assigned to the 2st OSS device. - (default: 1) - nonblock_open - Don't block opening busy PCM devices. + - Default: 1 + nonblock_open + - Don't block opening busy PCM devices. For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of the card #0. Similarly, when adsp_map=0, /dev/adsp will be mapped @@ -91,33 +91,39 @@ Module snd-rawmidi ------------------ - This module takes the options to change the mapping of OSS - devices like snd-pcm-oss module. + This module takes options which change the mapping of devices. + similar to those of the snd-pcm-oss module. midi_map - MIDI device number maps assigned to the 1st OSS device. - (default: 0) + - Default: 0 amidi_map - MIDI device number maps assigned to the 2st OSS device. - (default: 1) + - Default: 1 - Common parameters for top soundcard modules - ------------------------------------------- + Common parameters for top sound card modules + -------------------------------------------- - Each of top-level soundcard module takes some general options, + Each of top level sound card module takes the following options. - index - 0-7 - index (slot #) for soundcard - - if not set or -1, first free index (slot #) is assigned - id - user identification for card (up to 15 chars) - - default expression is 'card' (for example card1) - - value is used for /proc/asound filesystem - - this value can be used by applications for identification - of card if user does not want identify card with index number - enable - enable card. (all cards enabled for PCI and ISA PnP cards - as default.) + index - index (slot #) of sound card + - Values: 0 through 7 or negative + - If nonnegative, assign that index number + - if negative, interpret as a bitmask of permissible + indices; the first free permitted index is assigned + - Default: -1 + id - card ID (identifier or name) + - Can be up to 15 characters long + - Default: the card type + - A directory by this name is created under /proc/asound/ + containing information about the card + - This ID can be used instead of the index number in + identifying the card + enable - enable card + - Default: enabled, for PCI and ISA PnP cards Module snd-ad1816a ------------------ - Module for soundcards based on Analog Devices AD1816A/AD1815 ISA chips. + Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips. port - port # for AD1816A chip (PnP setup) mpu_port - port # for MPU-401 UART (PnP setup) @@ -132,7 +138,7 @@ Module snd-ad1848 ----------------- - Module for soundcards based on AD1848/AD1847/CS4248 ISA chips. + Module for sound cards based on AD1848/AD1847/CS4248 ISA chips. port - port # for AD1848 chip irq - IRQ # for AD1848 chip @@ -147,7 +153,8 @@ Module for ALi M5451 PCI chip. pcm_channels - Number of hardware channels assigned for PCM - spdif - Support SPDIF I/O (disabled by default) + spdif - Support SPDIF I/O + - Default: disabled Module supports autoprobe and multiple chips (max 8). @@ -156,7 +163,7 @@ Module snd-als100 ----------------- - Module for soundcards based on Avance Logic ALS100/ALS120 ISA chips. + Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips. port - port # for ALS100 (SB16) chip (PnP setup) irq - IRQ # for ALS100 (SB16) chip (PnP setup) @@ -171,7 +178,7 @@ Module snd-als4000 ------------------ - Module for soundcards based on Avance Logic ALS4000 PCI chip. + Module for sound cards based on Avance Logic ALS4000 PCI chip. joystick_port - port # for legacy joystick support. 0 = disabled (default), 1 = auto-detect @@ -197,6 +204,9 @@ Module supports up to 8 cards. + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-au8810, snd-au8820, snd-au8830 ----------------------------------------- @@ -226,7 +236,7 @@ Module snd-azt2320 ------------------ - Module for soundcards based on Aztech System AZT2320 ISA chip (PnP only). + Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only). port - port # for AZT2320 chip (PnP setup) wss_port - port # for WSS (PnP setup) @@ -242,7 +252,7 @@ Module snd-azt3328 ------------------ - Module for soundcards based on Aztech AZF3328 PCI chip. + Module for sound cards based on Aztech AZF3328 PCI chip. joystick - Enable joystick (default off) @@ -258,6 +268,9 @@ Module supports up to 8 cards. + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-ca0106 ----------------- @@ -269,7 +282,7 @@ Module snd-cmi8330 ------------------ - Module for soundcards based on C-Media CMI8330 ISA chips. + Module for sound cards based on C-Media CMI8330 ISA chips. wssport - port # for CMI8330 chip (WSS) wssirq - IRQ # for CMI8330 chip (WSS) @@ -284,7 +297,7 @@ Module snd-cmipci ----------------- - Module for C-Media CMI8338 and 8738 PCI soundcards. + Module for C-Media CMI8338 and 8738 PCI sound cards. mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default) fm_port - 0x388 (default), 0 = disable (default) @@ -297,7 +310,7 @@ Module snd-cs4231 ----------------- - Module for soundcards based on CS4231 ISA chips. + Module for sound cards based on CS4231 ISA chips. port - port # for CS4231 chip mpu_port - port # for MPU-401 UART (optional), -1 = disable @@ -314,7 +327,7 @@ Module snd-cs4232 ----------------- - Module for soundcards based on CS4232/CS4232A ISA chips. + Module for sound cards based on CS4232/CS4232A ISA chips. port - port # for CS4232 chip (PnP setup - 0x534) cport - control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00) @@ -334,7 +347,7 @@ Module snd-cs4236 ----------------- - Module for soundcards based on CS4235/CS4236/CS4236B/CS4237B/ + Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/ CS4238B/CS4239 ISA chips. port - port # for CS4236 chip (PnP setup - 0x534) @@ -367,7 +380,7 @@ Module snd-cs46xx ----------------- - Module for PCI soundcards based on CS4610/CS4612/CS4614/CS4615/CS4622/ + Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/ CS4624/CS4630/CS4280 PCI chips. external_amp - Force to enable external amplifer. @@ -400,14 +413,14 @@ Module snd-dummy ---------------- - Module for the dummy soundcard. This soundcard doesn't do any output + Module for the dummy sound card. This "card" doesn't do any output or input, but you may use this module for any application which - requires a soundcard (like RealPlayer). + requires a sound card (like RealPlayer). Module snd-emu10k1 ------------------ - Module for EMU10K1/EMU10k2 based PCI soundcards. + Module for EMU10K1/EMU10k2 based PCI sound cards. * Sound Blaster Live! * Sound Blaster PCI 512 * Emu APS (partially supported) @@ -447,7 +460,7 @@ Module snd-ens1370 ------------------ - Module for Ensoniq AudioPCI ES1370 PCI soundcards. + Module for Ensoniq AudioPCI ES1370 PCI sound cards. * SoundBlaster PCI 64 * SoundBlaster PCI 128 @@ -458,7 +471,7 @@ Module snd-ens1371 ------------------ - Module for Ensoniq AudioPCI ES1371 PCI soundcards. + Module for Ensoniq AudioPCI ES1371 PCI sound cards. * SoundBlaster PCI 64 * SoundBlaster PCI 128 * SoundBlaster Vibra PCI @@ -471,7 +484,7 @@ Module snd-es968 ---------------- - Module for soundcards based on ESS ES968 chip (PnP only). + Module for sound cards based on ESS ES968 chip (PnP only). port - port # for ES968 (SB8) chip (PnP setup) irq - IRQ # for ES968 (SB8) chip (PnP setup) @@ -482,7 +495,7 @@ Module snd-es1688 ----------------- - Module for ESS AudioDrive ES-1688 and ES-688 soundcards. + Module for ESS AudioDrive ES-1688 and ES-688 sound cards. port - port # for ES-1688 chip (0x220,0x240,0x260) mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default) @@ -495,7 +508,7 @@ Module snd-es18xx ----------------- - Module for ESS AudioDrive ES-18xx soundcards. + Module for ESS AudioDrive ES-18xx sound cards. port - port # for ES-18xx chip (0x220,0x240,0x260) mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default) @@ -514,14 +527,14 @@ Module snd-es1938 ----------------- - Module for soundcards based on ESS Solo-1 (ES1938,ES1946) chips. + Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips. Module supports up to 8 cards and autoprobe. Module snd-es1968 ----------------- - Module for soundcards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips. + Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips. total_bufsize - total buffer size in kB (1-4096kB) pcm_substreams_p - playback channels (1-8, default=2) @@ -539,7 +552,7 @@ Module snd-fm801 ---------------- - Module for ForteMedia FM801 based PCI soundcards. + Module for ForteMedia FM801 based PCI sound cards. tea575x_tuner - Enable TEA575x tuner - 1 = MediaForte 256-PCS @@ -553,7 +566,7 @@ Module snd-gusclassic --------------------- - Module for Gravis UltraSound Classic soundcard. + Module for Gravis UltraSound Classic sound card. port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260) irq - IRQ # for GF1 chip (3,5,9,11,12,15) @@ -568,7 +581,7 @@ Module snd-gusextreme --------------------- - Module for Gravis UltraSound Extreme (Synergy ViperMax) soundcard. + Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card. port - port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260) gf1_port - port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270) @@ -587,7 +600,7 @@ Module snd-gusmax ----------------- - Module for Gravis UltraSound MAX soundcard. + Module for Gravis UltraSound MAX sound card. port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260) irq - IRQ # for GF1 chip (3,5,9,11,12,15) @@ -599,18 +612,42 @@ Module supports up to 8 cards and autoprobe. + Module snd-hda-intel + -------------------- + + Module for Intel HD Audio (ICH6, ICH6M, ICH7) + + model - force the model name + + Module supports up to 8 cards. + + Each codec may have a model table for different configurations. + If your machine isn't listed there, the default (usually minimal) + configuration is set up. You can pass "model=" option to + specify a certain model in such a case. There are different + models depending on the codec chip. + + Model name Description + ---------- ----------- + ALC880 + 3stack 3-jack in back and a headphone out + 3stack-digout 3-jack in back, a HP out and a SPDIF out + 5stack 5-jack in back, 2-jack in front + 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out + w810 3-jack + + CMI9880 + minimal 3-jack in back + min_fp 3-jack in back, 2-jack in front + full 6-jack in back, 2-jack in front + full_dig 6-jack in back, 2-jack in front, SPDIF I/O + allout 5-jack in back, 2-jack in front, SPDIF out + Module snd-hdsp --------------- Module for RME Hammerfall DSP audio interface(s) - precise_ptr - Enable precise pointer (doesn't work reliably). - (default = 0) - line_outs_monitor - Send all input and playback streams to line outs - by default. (default = 0) - force_firmware - Force a reload of the I/O box firmware - (default = 0) - Module supports up to 8 cards. Note: The firmware data can be automatically loaded via hotplug @@ -628,7 +665,7 @@ Module snd-ice1712 ------------------ - Module for Envy24 (ICE1712) based PCI soundcards. + Module for Envy24 (ICE1712) based PCI sound cards. * MidiMan M Audio Delta 1010 * MidiMan M Audio Delta 1010LT * MidiMan M Audio Delta DiO 2496 @@ -660,7 +697,7 @@ Module snd-ice1724 ------------------ - Module for Envy24HT (VT/ICE1724) based PCI soundcards. + Module for Envy24HT (VT/ICE1724) based PCI sound cards. * MidiMan M Audio Revolution 7.1 * AMP Ltd AUDIO2000 * TerraTec Aureon Sky-5.1, Space-7.1 @@ -689,7 +726,7 @@ hp_only = use headphone control as master swap_hp = swap headphone and master controls swap_surround = swap master and surround controls - ad_shring = for AD1985, turn on OMS bit and use headphone + ad_sharing = for AD1985, turn on OMS bit and use headphone alc_jack = for ALC65x, turn on the jack sense mode inv_eapd = inverted EAPD implementation mute_led = bind EAPD bit for turning on/off mute LED @@ -726,11 +763,14 @@ This module supports up to 8 cards and autoprobe. + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-interwave -------------------- Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32 - and other soundcards based on AMD InterWave (tm) chip. + and other sound cards based on AMD InterWave (tm) chip. port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260) irq - IRQ # for InterWave chip (3,5,9,11,12,15) @@ -747,8 +787,8 @@ Module snd-interwave-stb ------------------------ - Module for UltraSound 32-Pro (soundcard from STB used by Compaq) - and other soundcards based on AMD InterWave (tm) chip with TEA6330T + Module for UltraSound 32-Pro (sound card from STB used by Compaq) + and other sound cards based on AMD InterWave (tm) chip with TEA6330T circuit for extended control of bass, treble and master volume. port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260) @@ -794,7 +834,7 @@ Module snd-mixart ----------------- - Module for Digigram miXart8 soundcards. + Module for Digigram miXart8 sound cards. Module supports multiple cards. Note: One miXart8 board will be represented as 4 alsa cards. @@ -813,10 +853,9 @@ port - port number or -1 (disable) irq - IRQ number or -1 (disable) - acpipnp - ACPI PnP detection - 0 = disable, 1 = enable (default) + pnp - PnP detection - 0 = disable, 1 = enable (default) - Module supports multiple devices (max 8) and ACPI PnP. If PnP is not - used (or ACPI not enabled), port and irq must be specified. + Module supports multiple devices (max 8) and PnP. Module snd-mtpav ---------------- @@ -883,7 +922,7 @@ Module snd-opl3sa2 ------------------ - Module for Yamaha OPL3-SA2/SA3 soundcards. + Module for Yamaha OPL3-SA2/SA3 sound cards. port - control port # for OPL3-SA chip (0x370) sb_port - SB port # for OPL3-SA chip (0x220,0x240) @@ -903,7 +942,7 @@ Module snd-opti92x-ad1848 ------------------------- - Module for soundcards based on OPTi 82c92x and Analog Devices AD1848 chips. + Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips. Module works with OAK Mozart cards as well. port - port # for WSS chip (0x530,0xe80,0xf40,0x604) @@ -918,7 +957,7 @@ Module snd-opti92x-cs4231 ------------------------- - Module for soundcards based on OPTi 82c92x and Crystal CS4231 chips. + Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips. port - port # for WSS chip (0x530,0xe80,0xf40,0x604) mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330) @@ -933,7 +972,7 @@ Module snd-opti93x ------------------ - Module for soundcards based on OPTi 82c93x chips. + Module for sound cards based on OPTi 82c93x chips. port - port # for WSS chip (0x530,0xe80,0xf40,0x604) mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330) @@ -962,21 +1001,21 @@ ---------------- Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32, - Prodif96 and Prodif Gold) soundcards. + Prodif96 and Prodif Gold) sound cards. Module supports up to 8 cards. Module snd-rme96 ---------------- - Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST soundcards. + Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards. Module supports up to 8 cards. Module snd-rme9652 ------------------ - Module for RME Digi9652 (Hammerfall, Hammerfall-Light) soundcards. + Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards. precise_ptr - Enable precise pointer (doesn't work reliably). (default = 0) @@ -992,7 +1031,7 @@ Module snd-sa11xx-uda1341 (on arm only) --------------------------------------- - Module for Philips UDA1341TS on Compaq iPAQ H3600 soundcard. + Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card. Module supports only one card. Module has no enable and index options. @@ -1039,7 +1078,7 @@ Module snd-sgalaxy ------------------ - Module for Aztech Sound Galaxy soundcard. + Module for Aztech Sound Galaxy sound card. sbport - Port # for SB16 interface (0x220,0x240) wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604) @@ -1079,7 +1118,7 @@ Module snd-wavefront -------------------- - Module for Turtle Beach Maui, Tropez and Tropez+ soundcards. + Module for Turtle Beach Maui, Tropez and Tropez+ sound cards. cs4232_pcm_port - Port # for CS4232 PCM interface. cs4232_pcm_irq - IRQ # for CS4232 PCM interface (5,7,9,11,12,15). @@ -1099,7 +1138,7 @@ Module snd-sonicvibes --------------------- - Module for S3 SonicVibes PCI soundcards. + Module for S3 SonicVibes PCI sound cards. * PINE Schubert 32 PCI reverb - Reverb Enable - 1 = enable, 0 = disable (default) @@ -1131,7 +1170,7 @@ Module snd-trident ------------------ - Module for Trident 4DWave DX/NX soundcards. + Module for Trident 4DWave DX/NX sound cards. * Best Union Miss Melody 4DWave PCI * HIS 4DWave PCI * Warpspeed ONSpeed 4DWave PCI @@ -1223,6 +1262,9 @@ Module supports up to 8 cards. + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-virmidi ------------------ @@ -1266,10 +1308,6 @@ Module for Digigram VX-Pocket VX2 PCMCIA card. - irq_mask - IRQ bitmask, specifies the available IRQs as bits - (default = 0xffff, all available) - irq_list - List of available interrupts (default = -1, not specified) - 4 numbers must be given (if specified). ibl - Capture IBL size. (default = 0, minimum size) Module supports up to 8 cards. The module is compiled only when @@ -1284,9 +1322,6 @@ When no hotplug fw loader is available, you need to load the firmware via vxloader utility in alsa-tools package. - The irq_mask and irq_list are provided to avoid allocation of - specific IRQs. Usually you don't need to specify them. - About capture IBL, see the description of snd-vx222 module. Note: the driver is build only when CONFIG_ISA is set. @@ -1296,9 +1331,6 @@ Module for Digigram VX-Pocket 440 PCMCIA card. - irq_mask - IRQ bitmask, specifies the available IRQs as bits - irq_list - List of available interrupts (default = -1, not specified) - 4 numbers must be given (if specified). ibl - Capture IBL size. (default = 0, minimum size) Module supports up to 8 cards. The module is compiled only when @@ -1313,9 +1345,6 @@ When no hotplug fw loader is available, you need to load the firmware via vxloader utility in alsa-tools package. - The irq_mask and irq_list are provided to avoid allocation of - specific IRQs. Usually you don't need to specify them. - About capture IBL, see the description of snd-vx222 module. Note: the driver is build only when CONFIG_ISA is set. @@ -1340,10 +1369,7 @@ Module snd-pdaudiocf -------------------- - Module for Sound Core PDAudioCF soundcard. - - irq_mask - IRQ mask (PCMCIA type) - irq_list - List of available interrupts for this soundcard + Module for Sound Core PDAudioCF sound card. Note: the driver is build only when CONFIG_ISA is set. @@ -1366,7 +1392,7 @@ The ALSA drivers can be loaded automatically on demand by defining module aliases. The string 'snd-card-%1' is requested for ALSA native -devices where %i is soundcard number from zero to seven. +devices where %i is sound card number from zero to seven. To auto-load an ALSA driver for OSS services, define the string 'sound-slot-%i' where %i means the slot number for OSS, which @@ -1379,16 +1405,16 @@ alias sound-slot-0 snd-emu10k1 ----- /etc/modprobe.conf -The available number of auto-loaded soundcards depends on the module +The available number of auto-loaded sound cards depends on the module option "cards_limit" of snd module. As default it's set to 1. To enable the auto-loading of multiple cards, specify the number of -soundcards in that option. +sound cards in that option. When multiple cards are available, it'd better to specify the index number for each card via module option, too, so that the order of cards is kept consistent. -An example configuration for two soundcards is like below: +An example configuration for two sound cards is like below: ----- /etc/modprobe.conf # ALSA portion @@ -1420,7 +1446,7 @@ /dev/snd/pcmC2D1[c|p] -> /dev/adsp2 -> minor 12+32 = 44 The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means -soundcard number and second means device number. The ALSA devices +sound card number and second means device number. The ALSA devices have either 'c' or 'p' suffix indicating the direction, capture and playback, respectively. diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 2005-03-03 21:43:47 -08:00 +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 2005-03-03 21:43:47 -08:00 @@ -110,9 +110,9 @@ - One is the the trees provided as a tarball or via cvs from the + One is the trees provided as a tarball or via cvs from the ALSA's ftp site, and another is the 2.6 (or later) Linux kernel - tree. To synchronize both, the ALSA driver tree is split to + tree. To synchronize both, the ALSA driver tree is split into two different trees: alsa-kernel and alsa-driver. The former contains purely the source codes for the Linux 2.6 (or later) tree. This tree is designed only for compilation on 2.6 or @@ -766,7 +766,7 @@ - The ALSA interfaces like PCM or control API are define in other + The ALSA interfaces like PCM or control API are defined in other header files as <sound/xxx.h>. They have to be included after <sound/core.h>. @@ -1103,7 +1103,7 @@ /* release the irq */ if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - /* release the i/o ports */ + /* release the i/o ports & memory */ pci_release_regions(chip->pci); /* disable the PCI entry */ pci_disable_device(chip->pci); @@ -1314,6 +1314,7 @@ + It will reserve the i/o port region of 8 bytes of the given PCI device. The returned value, chip->res_port, is allocated via kmalloc() by @@ -1936,6 +1937,7 @@ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops); /* pre-allocation of buffers */ + /* NOTE: this may fail */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024); @@ -1950,7 +1952,7 @@
Constructor - A pcm instance is allocated snd_pcm_new() + A pcm instance is allocated by snd_pcm_new() function. It would be better to create a constructor for pcm, namely, @@ -2235,7 +2237,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 -- */ @@ -2250,7 +2253,7 @@ For the operators (callbacks) of each sound driver, most of these records are supposed to be read-only. Only the PCM - middle-layer changes / updates these info. The excpetions are + middle-layer changes / updates these info. The exceptions are the hardware description (hw), interrupt callbacks (transfer_ack_xxx), DMA buffer information, and the private data. Besides, if you use the standard buffer allocation @@ -3250,7 +3253,7 @@ There are many different constraints. - Look in sound/asound.h for a complete list. + Look in sound/pcm.h for a complete list. You can even define your own constraint rules. For example, let's suppose my_chip can manage a substream of 1 channel if and only if the format is S16_LE, otherwise it supports any format @@ -4066,7 +4069,7 @@ Both snd_ac97_write() and snd_ac97_update() functions are used to set a value to the given register - (AC97_XXX). The different between them is + (AC97_XXX). The difference between them is that snd_ac97_update() doesn't write a value if the given value has been already set, while snd_ac97_write() always rewrites the @@ -4152,8 +4155,8 @@ Proc Files The ALSA AC97 interface will create a proc file such as - /proc/asound/card0/ac97#0 and - ac97#0regs. You can refer to these files to + /proc/asound/card0/codec97#0/ac97#0-0 and + ac97#0-0+regs. You can refer to these files to see the current status and registers of the codec.
@@ -4633,7 +4636,7 @@ where size is the byte size to be pre-allocated and the max is the maximal size to be changed via prealloc proc file. - The allocator will try to get as the large area as possible + The allocator will try to get as large area as possible within the given size.
@@ -4855,7 +4858,7 @@ If your hardware supports the page table like emu10k1 or the buffer descriptors like via82xx, you can use the scatter-gather (SG) DMA. ALSA provides an interface for handling SG-buffers. - The API is provided in <sound/pcm_sgbuf.h>. + The API is provided in <sound/pcm.h>. @@ -5159,12 +5162,12 @@ pm_private_data; diff -Nru a/Documentation/sound/alsa/VIA82xx-mixer.txt b/Documentation/sound/alsa/VIA82xx-mixer.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/sound/alsa/VIA82xx-mixer.txt 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,8 @@ + + VIA82xx mixer + ============= + +On many VIA82xx boards, the 'Input Source Select' mixer control does not work. +Setting it to 'Input2' on such boards will cause recording to hang, or fail +with EIO (input/output error) via OSS emulation. This control should be left +at 'Input1' for such cards. diff -Nru a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/sound/alsa/hda_codec.txt 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,299 @@ +Notes on Universal Interface for Intel High Definition Audio Codec +------------------------------------------------------------------ + +Takashi Iwai + + +[Still a draft version] + + +General +======= + +The snd-hda-codec module supports the generic access function for the +High Definition (HD) audio codecs. It's designed to be independent +from the controller code like ac97 codec module. The real accessors +from/to the controller must be implemented in the lowlevel driver. + +The structure of this module is similar with ac97_codec module. +Each codec chip belongs to a bus class which communicates with the +controller. + + +Initialization of Bus Instance +============================== + +The card driver has to create struct hda_bus at first. The template +struct should be filled and passed to the constructor: + +struct hda_bus_template { + void *private_data; + struct pci_dev *pci; + const char *modelname; + struct hda_bus_ops ops; +}; + +The card driver can set and use the private_data field to retrieve its +own data in callback functions. The pci field is used when the patch +needs to check the PCI subsystem IDs, so on. For non-PCI system, it +doesn't have to be set, of course. +The modelname field specifies the board's specific configuration. The +string is passed to the codec parser, and it depends on the parser how +the string is used. +These fields, private_data, pci and modelname are all optional. + +The ops field contains the callback functions as the following: + +struct hda_bus_ops { + int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm); + unsigned int (*get_response)(struct hda_codec *codec); + void (*private_free)(struct hda_bus *); +}; + +The command callback is called when the codec module needs to send a +VERB to the controller. It's always a single command. +The get_response callback is called when the codec requires the answer +for the last command. These two callbacks are mandatory and have to +be given. +The last, private_free callback, is optional. It's called in the +destructor to release any necessary data in the lowlevel driver. + +The bus instance is created via snd_hda_bus_new(). You need to pass +the card instance, the template, and the pointer to store the +resultant bus instance. + +int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp, + struct hda_bus **busp); + +It returns zero if successful. A negative return value means any +error during creation. + + +Creation of Codec Instance +========================== + +Each codec chip on the board is then created on the BUS instance. +To create a codec instance, call snd_hda_codec_new(). + +int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, + struct hda_codec **codecp); + +The first argument is the BUS instance, the second argument is the +address of the codec, and the last one is the pointer to store the +resultant codec instance (can be NULL if not needed). + +The codec is stored in a linked list of bus instance. You can follow +the codec list like: + + struct list_head *p; + struct hda_codec *codec; + list_for_each(p, &bus->codec_list) { + codec = list_entry(p, struct hda_codec, list); + ... + } + +The codec isn't initialized at this stage properly. The +initialization sequence is called when the controls are built later. + + +Codec Access +============ + +To access codec, use snd_codec_read() and snd_codec_write(). +snd_hda_param_read() is for reading parameters. +For writing a sequence of verbs, use snd_hda_sequence_write(). + +To retrieve the number of sub nodes connected to the given node, use +snd_hda_get_sub_nodes(). The connection list can be obtained via +snd_hda_get_connections() call. + +When an unsolicited event happens, pass the event via +snd_hda_queue_unsol_event() so that the codec routines will process it +later. + + +(Mixer) Controls +================ + +To create mixer controls of all codecs, call +snd_hda_build_controls(). It then builds the mixers and does +initialization stuff on each codec. + + +PCM Stuff +========= + +snd_hda_build_pcms() gives the necessary information to create PCM +streams. When it's called, each codec belonging to the bus stores +codec->num_pcms and codec->pcm_info fields. The num_pcms indicates +the number of elements in pcm_info array. The card driver is supposed +to traverse the codec linked list, read the pcm information in +pcm_info array, and build pcm instances according to them. + +The pcm_info array contains the following record: + +/* PCM information for each substream */ +struct hda_pcm_stream { + unsigned int substreams; /* number of substreams, 0 = not exist */ + unsigned int channels_min; /* min. number of channels */ + unsigned int channels_max; /* max. number of channels */ + hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ + u32 rates; /* supported rates */ + u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */ + unsigned int maxbps; /* supported max. bit per sample */ + struct hda_pcm_ops ops; +}; + +/* for PCM creation */ +struct hda_pcm { + char *name; + struct hda_pcm_stream stream[2]; +}; + +The name can be passed to snd_pcm_new(). The stream field contains +the information for playback (SNDRV_PCM_STREAM_PLAYBACK = 0) and +capture (SNDRV_PCM_STREAM_CAPTURE = 1) directions. The card driver +should pass substreams to snd_pcm_new() for the number of substreams +to create. + +The channels_min, channels_max, rates and formats should be copied to +runtime->hw record. They and maxbps fields are used also to compute +the format value for the HDA codec and controller. Call +snd_hda_calc_stream_format() to get the format value. + +The ops field contains the following callback functions: + +struct hda_pcm_ops { + int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec, + snd_pcm_substream_t *substream); + int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec, + snd_pcm_substream_t *substream); + int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec, + unsigned int stream_tag, unsigned int format, + snd_pcm_substream_t *substream); + int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec, + snd_pcm_substream_t *substream); +}; + +All are non-NULL, so you can call them safely without NULL check. + +The open callback should be called in PCM open after runtime->hw is +set up. It may override some setting and constraints additionally. +Similarly, the close callback should be called in the PCM close. + +The prepare callback should be called in PCM prepare. This will set +up the codec chip properly for the operation. The cleanup should be +called in hw_free to clean up the configuration. + +The caller should check the return value, at least for open and +prepare callbacks. When a negative value is returned, some error +occurred. + + +Proc Files +========== + +Each codec dumps the widget node information in +/proc/asound/card*/codec#* file. This information would be really +helpful for debugging. Please provide its contents together with the +bug report. + + +Power Management +================ + +It's simple: +Call snd_hda_suspend() in the PM suspend callback. +Call snd_hda_resume() in the PM resume callback. + + +Codec Preset (Patch) +==================== + +To set up and handle the codec functionality fully, each codec may +have a codec preset (patch). It's defined in struct hda_codec_preset: + + struct hda_codec_preset { + unsigned int id; + unsigned int mask; + unsigned int subs; + unsigned int subs_mask; + unsigned int rev; + const char *name; + int (*patch)(struct hda_codec *codec); + }; + +When the codec id and codec subsystem id match with the given id and +subs fields bitwise (with bitmask mask and subs_mask), the callback +patch is called. The patch callback should initialize the codec and +set the codec->patch_ops field. This is defined as below: + + struct hda_codec_ops { + int (*build_controls)(struct hda_codec *codec); + int (*build_pcms)(struct hda_codec *codec); + int (*init)(struct hda_codec *codec); + void (*free)(struct hda_codec *codec); + void (*unsol_event)(struct hda_codec *codec, unsigned int res); + #ifdef CONFIG_PM + int (*suspend)(struct hda_codec *codec, pm_message_t state); + int (*resume)(struct hda_codec *codec); + #endif + }; + +The build_controls callback is called from snd_hda_build_controls(). +Similarly, the build_pcms callback is called from +snd_hda_build_pcms(). The init callback is called after +build_controls to initialize the hardware. +The free callback is called as a destructor. + +The unsol_event callback is called when an unsolicited event is +received. + +The suspend and resume callbacks are for power management. + +Each entry can be NULL if not necessary to be called. + + +Generic Parser +============== + +When the device doesn't match with any given presets, the widgets are +parsed via th generic parser (hda_generic.c). Its support is +limited: no multi-channel support, for example. + + +Digital I/O +=========== + +Call snd_hda_create_spdif_out_ctls() from the patch to create controls +related with SPDIF out. In the patch resume callback, call +snd_hda_resume_spdif(). + + +Helper Functions +================ + +snd_hda_get_codec_name() stores the codec name on the given string. + +snd_hda_check_board_config() can be used to obtain the configuration +information matching with the device. Define the table with struct +hda_board_config entries (zero-terminated), and pass it to the +function. The function checks the modelname given as a module +parameter, and PCI subsystem IDs. If the matching entry is found, it +returns the config field value. + +snd_hda_add_new_ctls() can be used to create and add control entries. +Pass the zero-terminated array of snd_kcontrol_new_t. The same array +can be passed to snd_hda_resume_ctls() for resume. +Note that this will call control->put callback of these entries. So, +put callback should check codec->in_resume and force to restore the +given value if it's non-zero even if the value is identical with the +cached value. + +Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be +used for the entry of snd_kcontrol_new_t. + +The input MUX helper callbacks for such a control are provided, too: +snd_hda_input_mux_info() and snd_hda_input_mux_put(). See +patch_realtek.c for example. diff -Nru a/include/sound/ak4114.h b/include/sound/ak4114.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/sound/ak4114.h 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,205 @@ +#ifndef __SOUND_AK4114_H +#define __SOUND_AK4114_H + +/* + * Routines for Asahi Kasei AK4114 + * Copyright (c) by Jaroslav Kysela , + * + * + * 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 + * + */ + +/* AK4114 registers */ +#define AK4114_REG_PWRDN 0x00 /* power down */ +#define AK4114_REG_FORMAT 0x01 /* format control */ +#define AK4114_REG_IO0 0x02 /* input/output control */ +#define AK4114_REG_IO1 0x03 /* input/output control */ +#define AK4114_REG_INT0_MASK 0x04 /* interrupt0 mask */ +#define AK4114_REG_INT1_MASK 0x05 /* interrupt1 mask */ +#define AK4114_REG_RCS0 0x06 /* receiver status 0 */ +#define AK4114_REG_RCS1 0x07 /* receiver status 1 */ +#define AK4114_REG_RXCSB0 0x08 /* RX channel status byte 0 */ +#define AK4114_REG_RXCSB1 0x09 /* RX channel status byte 1 */ +#define AK4114_REG_RXCSB2 0x0a /* RX channel status byte 2 */ +#define AK4114_REG_RXCSB3 0x0b /* RX channel status byte 3 */ +#define AK4114_REG_RXCSB4 0x0c /* RX channel status byte 4 */ +#define AK4114_REG_TXCSB0 0x0d /* TX channel status byte 0 */ +#define AK4114_REG_TXCSB1 0x0e /* TX channel status byte 1 */ +#define AK4114_REG_TXCSB2 0x0f /* TX channel status byte 2 */ +#define AK4114_REG_TXCSB3 0x10 /* TX channel status byte 3 */ +#define AK4114_REG_TXCSB4 0x11 /* TX channel status byte 4 */ +#define AK4114_REG_Pc0 0x12 /* burst preamble Pc byte 0 */ +#define AK4114_REG_Pc1 0x13 /* burst preamble Pc byte 1 */ +#define AK4114_REG_Pd0 0x14 /* burst preamble Pd byte 0 */ +#define AK4114_REG_Pd1 0x15 /* burst preamble Pd byte 1 */ +#define AK4114_REG_QSUB_ADDR 0x16 /* Q-subcode address + control */ +#define AK4114_REG_QSUB_TRACK 0x17 /* Q-subcode track */ +#define AK4114_REG_QSUB_INDEX 0x18 /* Q-subcode index */ +#define AK4114_REG_QSUB_MINUTE 0x19 /* Q-subcode minute */ +#define AK4114_REG_QSUB_SECOND 0x1a /* Q-subcode second */ +#define AK4114_REG_QSUB_FRAME 0x1b /* Q-subcode frame */ +#define AK4114_REG_QSUB_ZERO 0x1c /* Q-subcode zero */ +#define AK4114_REG_QSUB_ABSMIN 0x1d /* Q-subcode absolute minute */ +#define AK4114_REG_QSUB_ABSSEC 0x1e /* Q-subcode absolute second */ +#define AK4114_REG_QSUB_ABSFRM 0x1f /* Q-subcode absolute frame */ + +/* sizes */ +#define AK4114_REG_RXCSB_SIZE ((AK4114_REG_RXCSB4-AK4114_REG_RXCSB0)+1) +#define AK4114_REG_TXCSB_SIZE ((AK4114_REG_TXCSB4-AK4114_REG_TXCSB0)+1) +#define AK4114_REG_QSUB_SIZE ((AK4114_REG_QSUB_ABSFRM-AK4114_REG_QSUB_ADDR)+1) + +/* AK4117_REG_PWRDN bits */ +#define AK4114_CS12 (1<<7) /* Channel Status Select */ +#define AK4114_BCU (1<<6) /* Block Start & C/U Output Mode */ +#define AK4114_CM1 (1<<5) /* Master Clock Operation Select */ +#define AK4114_CM0 (1<<4) /* Master Clock Operation Select */ +#define AK4114_OCKS1 (1<<3) /* Master Clock Frequency Select */ +#define AK4114_OCKS0 (1<<2) /* Master Clock Frequency Select */ +#define AK4114_PWN (1<<1) /* 0 = power down, 1 = normal operation */ +#define AK4114_RST (1<<0) /* 0 = reset & initialize (except this register), 1 = normal operation */ + +/* AK4114_REQ_FORMAT bits */ +#define AK4114_MONO (1<<7) /* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */ +#define AK4114_DIF2 (1<<5) /* Audio Data Control */ +#define AK4114_DIF1 (1<<5) /* Audio Data Control */ +#define AK4114_DIF0 (1<<4) /* Audio Data Control */ +#define AK4114_DIF_16R (0) /* STDO: 16-bit, right justified */ +#define AK4114_DIF_18R (AK4114_DIF0) /* STDO: 18-bit, right justified */ +#define AK4114_DIF_20R (AK4114_DIF1) /* STDO: 20-bit, right justified */ +#define AK4114_DIF_24R (AK4114_DIF1|AK4114_DIF0) /* STDO: 24-bit, right justified */ +#define AK4114_DIF_24L (AK4114_DIF2) /* STDO: 24-bit, left justified */ +#define AK4114_DIF_24I2S (AK4114_DIF2|AK4114_DIF0) /* STDO: I2S */ +#define AK4114_DIF_I24L (AK4114_DIF2|AK4114_DIF1) /* STDO: 24-bit, left justified; LRCLK, BICK = Input */ +#define AK4114_DIF_I24I2S (AK4114_DIF2|AK4114_DIF1|AK4114_DIF0) /* STDO: I2S; LRCLK, BICK = Input */ +#define AK4114_DEAU (1<<3) /* Deemphasis Autodetect Enable (1 = enable) */ +#define AK4114_DEM1 (1<<2) /* 32kHz-48kHz Deemphasis Control */ +#define AK4114_DEM0 (1<<1) /* 32kHz-48kHz Deemphasis Control */ +#define AK4114_DEM_44KHZ (0) +#define AK4114_DEM_48KHZ (AK4114_DEM1) +#define AK4114_DEM_32KHZ (AK4114_DEM0|AK4114_DEM1) +#define AK4114_DEM_96KHZ (AK4114_DEM1) /* DFS must be set */ +#define AK4114_DFS (1<<0) /* 96kHz Deemphasis Control */ + +/* AK4114_REG_IO0 */ +#define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */ +#define AK4114_OPS12 (1<<2) /* Output Though Data Selector for TX1 pin */ +#define AK4114_OPS11 (1<<1) /* Output Though Data Selector for TX1 pin */ +#define AK4114_OPS10 (1<<0) /* Output Though Data Selector for TX1 pin */ +#define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */ +#define AK4114_OPS02 (1<<2) /* Output Though Data Selector for TX0 pin */ +#define AK4114_OPS01 (1<<1) /* Output Though Data Selector for TX0 pin */ +#define AK4114_OPS00 (1<<0) /* Output Though Data Selector for TX0 pin */ + +/* AK4114_REG_IO1 */ +#define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */ +#define AK4114_EFH0 (1<<6) /* Interrupt 0 pin Hold */ +#define AK4114_EFH_512 (0) +#define AK4114_EFH_1024 (AK4114_EFH0) +#define AK4114_EFH_2048 (AK4114_EFH1) +#define AK4114_EFH_4096 (AK4114_EFH1|AK4114_EFH0) +#define AK4114_UDIT (1<<5) /* U-bit Control for DIT (0 = fixed '0', 1 = recovered) */ +#define AK4114_TLR (1<<4) /* Double Sampling Frequency Select for DIT (0 = L channel, 1 = R channel) */ +#define AK4114_DIT (1<<3) /* TX1 out: 0 = Through Data (RX data), 1 = Transmit Data (DAUX data) */ +#define AK4114_IPS2 (1<<2) /* Input Recovery Data Select */ +#define AK4114_IPS1 (1<<1) /* Input Recovery Data Select */ +#define AK4114_IPS0 (1<<0) /* Input Recovery Data Select */ +#define AK4114_IPS(x) ((x)&7) + +/* AK4114_REG_INT0_MASK && AK4114_REG_INT1_MASK*/ +#define AK4117_MQI (1<<7) /* mask enable for QINT bit */ +#define AK4117_MAT (1<<6) /* mask enable for AUTO bit */ +#define AK4117_MCI (1<<5) /* mask enable for CINT bit */ +#define AK4117_MUL (1<<4) /* mask enable for UNLOCK bit */ +#define AK4117_MDTS (1<<3) /* mask enable for DTSCD bit */ +#define AK4117_MPE (1<<2) /* mask enable for PEM bit */ +#define AK4117_MAN (1<<1) /* mask enable for AUDN bit */ +#define AK4117_MPR (1<<0) /* mask enable for PAR bit */ + +/* AK4114_REG_RCS0 */ +#define AK4114_QINT (1<<7) /* Q-subcode buffer interrupt, 0 = no change, 1 = changed */ +#define AK4114_AUTO (1<<6) /* Non-PCM or DTS stream auto detection, 0 = no detect, 1 = detect */ +#define AK4114_CINT (1<<5) /* channel status buffer interrupt, 0 = no change, 1 = change */ +#define AK4114_UNLCK (1<<4) /* PLL lock status, 0 = lock, 1 = unlock */ +#define AK4114_DTSCD (1<<3) /* DTS-CD Detect, 0 = No detect, 1 = Detect */ +#define AK4114_PEM (1<<2) /* Pre-emphasis Detect, 0 = OFF, 1 = ON */ +#define AK4114_AUDION (1<<1) /* audio bit output, 0 = audio, 1 = non-audio */ +#define AK4114_PAR (1<<0) /* parity error or biphase error status, 0 = no error, 1 = error */ + +/* AK4114_REG_RCS1 */ +#define AK4114_FS3 (1<<7) /* sampling frequency detection */ +#define AK4114_FS2 (1<<6) +#define AK4114_FS1 (1<<5) +#define AK4114_FS0 (1<<4) +#define AK4114_FS_44100HZ (0) +#define AK4114_FS_48000HZ (AK4114_FS1) +#define AK4114_FS_32000HZ (AK4114_FS1|AK4114_FS0) +#define AK4114_FS_88200HZ (AK4114_FS3) +#define AK4114_FS_96000HZ (AK4114_FS3|AK4114_FS1) +#define AK4114_FS_176400HZ (AK4114_FS3|AK4114_FS2) +#define AK4114_FS_192000HZ (AK4114_FS3|AK4114_FS2|AK4114_FS1) +#define AK4114_V (1<<3) /* Validity of Channel Status, 0 = Valid, 1 = Invalid */ +#define AK4114_QCRC (1<<1) /* CRC for Q-subcode, 0 = no error, 1 = error */ +#define AK4114_CCRC (1<<0) /* CRC for channel status, 0 = no error, 1 = error */ + +/* flags for snd_ak4114_check_rate_and_errors() */ +#define AK4114_CHECK_NO_STAT (1<<0) /* no statistics */ +#define AK4114_CHECK_NO_RATE (1<<1) /* no rate check */ + +#define AK4114_CONTROLS 14 + +typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data); +typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr); + +typedef struct ak4114 ak4114_t; + +struct ak4114 { + snd_card_t * card; + ak4114_write_t * write; + ak4114_read_t * read; + void * private_data; + unsigned int init: 1; + spinlock_t lock; + unsigned char regmap[7]; + unsigned char txcsb[5]; + snd_kcontrol_t *kctls[AK4114_CONTROLS]; + snd_pcm_substream_t *playback_substream; + snd_pcm_substream_t *capture_substream; + unsigned long parity_errors; + unsigned long v_bit_errors; + unsigned long qcrc_errors; + unsigned long ccrc_errors; + unsigned char rcs0; + unsigned char rcs1; + struct workqueue_struct *workqueue; + struct work_struct work; + void *change_callback_private; + void (*change_callback)(ak4114_t *ak4114, unsigned char c0, unsigned char c1); +}; + +int snd_ak4114_create(snd_card_t *card, + ak4114_read_t *read, ak4114_write_t *write, + unsigned char pgm[7], unsigned char txcsb[5], + void *private_data, ak4114_t **r_ak4114); +void snd_ak4114_reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char mask, unsigned char val); +void snd_ak4114_reinit(ak4114_t *ak4114); +int snd_ak4114_build(ak4114_t *ak4114, + snd_pcm_substream_t *playback_substream, + snd_pcm_substream_t *capture_substream); +int snd_ak4114_external_rate(ak4114_t *ak4114); +int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags); + +#endif /* __SOUND_AK4114_H */ + diff -Nru a/include/sound/ak4117.h b/include/sound/ak4117.h --- a/include/sound/ak4117.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/ak4117.h 2005-03-03 21:43:47 -08:00 @@ -106,7 +106,7 @@ #define AK4117_DIF_24L (AK4117_DIF2) /* STDO: 24-bit, left justified */ #define AK4117_DIF_24I2S (AK4117_DIF2|AK4117_DIF0) /* STDO: I2S */ -/* AK4117_REG_INT0_MASK & AK4117_INT1_MASK */ +/* AK4117_REG_INT0_MASK & AK4117_REG_INT1_MASK */ #define AK4117_MULK (1<<7) /* mask enable for UNLOCK bit */ #define AK4117_MPAR (1<<6) /* mask enable for PAR bit */ #define AK4117_MAUTO (1<<5) /* mask enable for AUTO bit */ @@ -181,8 +181,8 @@ int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write, unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117); -void snd_ak4117_reg_write(ak4117_t *chip, unsigned char reg, unsigned char mask, unsigned char val); -void snd_ak4117_reinit(ak4117_t *chip); +void snd_ak4117_reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char mask, unsigned char val); +void snd_ak4117_reinit(ak4117_t *ak4117); int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream); int snd_ak4117_external_rate(ak4117_t *ak4117); int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags); diff -Nru a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h --- a/include/sound/ak4xxx-adda.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/ak4xxx-adda.h 2005-03-03 21:43:47 -08:00 @@ -50,7 +50,8 @@ /* template should fill the following fields */ unsigned int idx_offset; /* control index offset */ enum { - SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381 + SND_AK4524, SND_AK4528, SND_AK4529, + SND_AK4355, SND_AK4358, SND_AK4381 } type; struct snd_ak4xxx_ops ops; }; diff -Nru a/include/sound/control.h b/include/sound/control.h --- a/include/sound/control.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/control.h 2005-03-03 21:43:47 -08:00 @@ -119,6 +119,13 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn); int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn); +#ifdef CONFIG_COMPAT +int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn); +int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn); +#else +#define snd_ctl_register_ioctl_compat(fcn) +#define snd_ctl_unregister_ioctl_compat(fcn) +#endif int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control); int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control); diff -Nru a/include/sound/core.h b/include/sound/core.h --- a/include/sound/core.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/core.h 2005-03-03 21:43:47 -08:00 @@ -26,6 +26,7 @@ #include /* struct semaphore */ #include /* struct rw_semaphore */ #include /* struct workqueue_struct */ +#include /* pm_message_t */ /* Typedef's */ typedef struct timespec snd_timestamp_t; @@ -167,13 +168,15 @@ struct device *dev; #ifdef CONFIG_PM - int (*pm_suspend)(snd_card_t *card, unsigned int state); - int (*pm_resume)(snd_card_t *card, unsigned int state); - struct pm_dev *pm_dev; /* for ISA */ + int (*pm_suspend)(snd_card_t *card, pm_message_t state); + int (*pm_resume)(snd_card_t *card); void *pm_private_data; unsigned int power_state; /* power state */ struct semaphore power_lock; /* power lock */ wait_queue_head_t power_sleep; +#ifdef CONFIG_SND_GENERIC_PM + struct snd_generic_device *pm_dev; /* for ISA */ +#endif #endif #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) @@ -206,36 +209,34 @@ wake_up(&card->power_sleep); } int snd_card_set_pm_callback(snd_card_t *card, - int (*suspend)(snd_card_t *, unsigned int), - int (*resume)(snd_card_t *, unsigned int), + int (*suspend)(snd_card_t *, pm_message_t), + int (*resume)(snd_card_t *), void *private_data); -int snd_card_set_dev_pm_callback(snd_card_t *card, int type, - int (*suspend)(snd_card_t *, unsigned int), - int (*resume)(snd_card_t *, unsigned int), - void *private_data); +int snd_card_set_generic_pm_callback(snd_card_t *card, + int (*suspend)(snd_card_t *, pm_message_t), + int (*resume)(snd_card_t *), + 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); + snd_card_set_generic_pm_callback(card, suspend, resume, data) +struct pci_dev; +int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t 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 + +#else /* ! CONFIG_PM */ + #define snd_power_lock(card) do { (void)(card); } while (0) #define snd_power_unlock(card) do { (void)(card); } while (0) static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; } #define snd_power_get_state(card) SNDRV_CTL_POWER_D0 #define snd_power_change_state(card, state) do { (void)(card); } while (0) #define snd_card_set_pm_callback(card,suspend,resume,data) -#define snd_card_set_dev_pm_callback(card,suspend,resume,data) +#define snd_card_set_generic_pm_callback(card,suspend,resume,data) #define snd_card_set_isa_pm_callback(card,suspend,resume,data) -#ifdef CONFIG_PCI #define SND_PCI_PM_CALLBACKS -#endif -#endif + +#endif /* CONFIG_PM */ /* device.c */ diff -Nru a/include/sound/emu10k1.h b/include/sound/emu10k1.h --- a/include/sound/emu10k1.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/emu10k1.h 2005-03-03 21:43:47 -08:00 @@ -51,7 +51,9 @@ #define NUM_MIDI 16 #define NUM_G 64 /* use all channels */ #define NUM_FXSENDS 4 +#define NUM_EFX_PLAYBACK 16 +/* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ #define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit */ @@ -82,10 +84,16 @@ /* Clear pending interrupts by writing a 1 to */ /* the relevant bits and zero to the other bits */ +#define IPR_GPIOMSG 0x20000000 /* GPIO message interrupt (RE'd, still not sure + which INTE bits enable it) */ + /* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ #define IPR_A_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */ #define IPR_A_MIDIRECVBUFEMPTY2 0x08000000 /* MIDI UART receive buffer empty */ +#define IPR_SPDIFBUFFULL 0x04000000 /* SPDIF capture related, 10k2 only? (RE) */ +#define IPR_SPDIFBUFHALFFULL 0x02000000 /* SPDIF capture related? (RE) */ + #define IPR_SAMPLERATETRACKER 0x01000000 /* Sample rate tracker lock status change */ #define IPR_FXDSP 0x00800000 /* Enable FX DSP interrupts */ #define IPR_FORCEINT 0x00400000 /* Force Sound Blaster interrupt */ @@ -104,12 +112,12 @@ #define IPR_INTERVALTIMER 0x00000200 /* Interval timer terminal count */ #define IPR_MIDITRANSBUFEMPTY 0x00000100 /* MIDI UART transmit buffer empty */ #define IPR_MIDIRECVBUFEMPTY 0x00000080 /* MIDI UART receive buffer empty */ -#define IPR_CHANNELLOOP 0x00000040 /* One or more channel loop interrupts pending */ +#define IPR_CHANNELLOOP 0x00000040 /* Channel (half) loop interrupt(s) pending */ #define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */ - /* Highest set channel in CLIPL or CLIPH. When */ - /* IP is written with CL set, the bit in CLIPL */ - /* or CLIPH corresponding to the CIN value */ - /* written will be cleared. */ + /* highest set channel in CLIPL, CLIPH, HLIPL, */ + /* or HLIPH. When IP is written with CL set, */ + /* the bit in H/CLIPL or H/CLIPH corresponding */ + /* to the CIN value written will be cleared. */ #define INTE 0x0c /* Interrupt enable register */ #define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ @@ -236,9 +244,27 @@ #define A_IOCFG 0x18 /* GPIO on Audigy card (16bits) */ #define A_GPINPUT_MASK 0xff00 #define A_GPOUTPUT_MASK 0x00ff -#define A_IOCFG_GPOUT0 0x0044 /* analog/digital? */ -#define A_IOCFG_GPOUT1 0x0002 /* IR */ + +// Audigy output/GPIO stuff taken from the kX drivers +#define A_IOCFG_GPOUT0 0x0044 /* analog/digital */ +#define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */ +#define A_IOCFG_ENABLE_DIGITAL 0x0004 +#define A_IOCFG_UNKNOWN_20 0x0020 +#define A_IOCFG_DISABLE_AC97_FRONT 0x0080 /* turn off ac97 front -> front (10k2.1) */ +#define A_IOCFG_GPOUT1 0x0002 /* IR? drive's internal bypass (?) */ #define A_IOCFG_GPOUT2 0x0001 /* IR */ +#define A_IOCFG_MULTIPURPOSE_JACK 0x2000 /* center+lfe+rear_center (a2/a2ex) */ + /* + digital for generic 10k2 */ +#define A_IOCFG_DIGITAL_JACK 0x1000 /* digital for a2 platinum */ +#define A_IOCFG_FRONT_JACK 0x4000 +#define A_IOCFG_REAR_JACK 0x8000 +#define A_IOCFG_PHONES_JACK 0x0100 /* LiveDrive */ + +/* outputs: + * for audigy2 platinum: 0xa00 + * for a2 platinum ex: 0x1c00 + * for a1 platinum: 0x0 + */ #define TIMER 0x1a /* Timer terminal count register */ /* NOTE: After the rate is changed, a maximum */ @@ -464,6 +490,8 @@ /* NOTE: All channels contain internal variables; do */ /* not write to these locations. */ +/* 1f something */ + #define CD0 0x20 /* Cache data 0 register */ #define CD1 0x21 /* Cache data 1 register */ #define CD2 0x22 /* Cache data 2 register */ @@ -481,6 +509,8 @@ #define CDE 0x2e /* Cache data E register */ #define CDF 0x2f /* Cache data F register */ +/* 0x30-3f seem to be the same as 0x20-2f */ + #define PTB 0x40 /* Page table base register */ #define PTB_MASK 0xfffff000 /* Physical address of the page table in host memory */ @@ -511,7 +541,11 @@ #define FXWC 0x43 /* FX output write channels register */ /* When set, each bit enables the writing of the */ - /* corresponding FX output channel into host memory */ + /* corresponding FX output channel (internal registers */ + /* 0x20-0x3f) to host memory. This mode of recording */ + /* is 16bit, 48KHz only. All 32 channels can be enabled */ + /* simultaneously. */ + #define FXWC_DEFAULTROUTE_C (1<<0) /* left emu out? */ #define FXWC_DEFAULTROUTE_B (1<<1) /* right emu out? */ #define FXWC_DEFAULTROUTE_A (1<<12) @@ -546,12 +580,16 @@ #define FXBA 0x47 /* FX Buffer Address */ #define FXBA_MASK 0xfffff000 /* 20 bit base address */ +/* 0x48 something - word access, defaults to 3f */ + #define MICBS 0x49 /* Microphone buffer size register */ #define ADCBS 0x4a /* ADC buffer size register */ #define FXBS 0x4b /* FX buffer size register */ +/* register: 0x4c..4f: ffff-ffff current amounts, per-channel */ + /* The following mask values define the size of the ADC, MIX and FX buffers in bytes */ #define ADCBS_BUFSIZE_NONE 0x00000000 #define ADCBS_BUFSIZE_384 0x00000001 @@ -602,6 +640,7 @@ #define A_DBG_SATURATION_OCCURED 0x20000000 #define A_DBG_SATURATION_ADDR 0x0ffc0000 +// NOTE: 0x54,55,56: 64-bit #define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ #define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ @@ -657,6 +696,7 @@ #define AC97SLOT_CNTR 0x10 /* Center enable */ #define AC97SLOT_LFE 0x20 /* LFE enable */ +// NOTE: 0x60,61,62: 64-bit #define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ #define GPSRCS 0x61 /* General Purpose SPDIF sample rate cvt status */ @@ -693,6 +733,19 @@ #define FXIDX_MASK 0x0000ffff /* 16-bit value */ #define FXIDX_IDX 0x10000065 +/* The 32-bit HLIx and HLIPx registers all have one bit per channel control/status */ +#define HLIEL 0x66 /* Channel half loop interrupt enable low register */ + +#define HLIEH 0x67 /* Channel half loop interrupt enable high register */ + +#define HLIPL 0x68 /* Channel half loop interrupt pending low register */ + +#define HLIPH 0x69 /* Channel half loop interrupt pending high register */ + +// 0x6a,6b,6c used for some recording +// 0x6d unused +// 0x6e,6f - tanktable base / offset + /* This is the MPU port on the card (via the game port) */ #define A_MUDATA1 0x70 #define A_MUCMD1 0x71 @@ -710,10 +763,14 @@ #define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */ #define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */ -#define A_SPDIF_48000 0x00000080 -#define A_SPDIF_44100 0x00000000 +#define A_SPDIF_RATE_MASK 0x000000c0 +#define A_SPDIF_48000 0x00000000 +#define A_SPDIF_44100 0x00000080 #define A_SPDIF_96000 0x00000040 +/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell */ +/* 0x7a, 0x7b - lookup tables */ + #define A_FXRT2 0x7c #define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ #define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */ @@ -725,7 +782,8 @@ #define A_FXSENDAMOUNT_F_MASK 0x00FF0000 #define A_FXSENDAMOUNT_G_MASK 0x0000FF00 #define A_FXSENDAMOUNT_H_MASK 0x000000FF - +/* 0x7c, 0x7e "high bit is used for filtering" */ + /* The send amounts for this one are the same as used with the emu10k1 */ #define A_FXRT1 0x7e #define A_FXRT_CHANNELA 0x0000003f @@ -782,6 +840,7 @@ typedef struct _snd_emu10k1_pcm emu10k1_pcm_t; typedef enum { + EMU10K1_EFX, EMU10K1_PCM, EMU10K1_SYNTH, EMU10K1_MIDI @@ -790,8 +849,9 @@ struct _snd_emu10k1_voice { emu10k1_t *emu; int number; - int use: 1, + unsigned int use: 1, pcm: 1, + efx: 1, synth: 1, midi: 1; void (*interrupt)(emu10k1_t *emu, emu10k1_voice_t *pvoice); @@ -801,6 +861,7 @@ typedef enum { PLAYBACK_EMUVOICE, + PLAYBACK_EFX, CAPTURE_AC97ADC, CAPTURE_AC97MIC, CAPTURE_EFX @@ -810,7 +871,7 @@ emu10k1_t *emu; snd_emu10k1_pcm_type_t type; snd_pcm_substream_t *substream; - emu10k1_voice_t *voices[2]; + emu10k1_voice_t *voices[NUM_EFX_PLAYBACK]; emu10k1_voice_t *extra; unsigned short running; unsigned short first_ptr; @@ -938,7 +999,7 @@ int irq; unsigned long port; /* I/O port number */ - int APS: 1, /* APS flag */ + unsigned int APS: 1, /* APS flag */ no_ac97: 1, /* no AC'97 */ tos_link: 1, /* tos link detected */ rear_ac97: 1, /* rear channels are on AC'97 */ @@ -984,23 +1045,27 @@ spinlock_t voice_lock; struct semaphore ptb_lock; - emu10k1_voice_t voices[64]; + emu10k1_voice_t voices[NUM_G]; emu10k1_pcm_mixer_t pcm_mixer[32]; + emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK]; snd_kcontrol_t *ctl_send_routing; snd_kcontrol_t *ctl_send_volume; snd_kcontrol_t *ctl_attn; + snd_kcontrol_t *ctl_efx_send_routing; + snd_kcontrol_t *ctl_efx_send_volume; + snd_kcontrol_t *ctl_efx_attn; void (*hwvol_interrupt)(emu10k1_t *emu, unsigned int status); void (*capture_interrupt)(emu10k1_t *emu, unsigned int status); void (*capture_mic_interrupt)(emu10k1_t *emu, unsigned int status); void (*capture_efx_interrupt)(emu10k1_t *emu, unsigned int status); - void (*timer_interrupt)(emu10k1_t *emu); void (*spdif_interrupt)(emu10k1_t *emu, unsigned int status); void (*dsp_interrupt)(emu10k1_t *emu); snd_pcm_substream_t *pcm_capture_substream; snd_pcm_substream_t *pcm_capture_mic_substream; snd_pcm_substream_t *pcm_capture_efx_substream; + snd_pcm_substream_t *pcm_playback_efx_substream; snd_timer_t *timer; @@ -1008,6 +1073,7 @@ emu10k1_midi_t midi2; /* for audigy */ unsigned int efx_voices_mask[2]; + unsigned int next_free_voice; }; int snd_emu10k1_create(snd_card_t * card, @@ -1021,6 +1087,7 @@ int snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm); int snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm); int snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm); +int snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm); int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm); int snd_emu10k1_mixer(emu10k1_t * emu); int snd_emu10k1_timer(emu10k1_t * emu, int device); @@ -1043,6 +1110,9 @@ void snd_emu10k1_voice_intr_enable(emu10k1_t *emu, unsigned int voicenum); void snd_emu10k1_voice_intr_disable(emu10k1_t *emu, unsigned int voicenum); void snd_emu10k1_voice_intr_ack(emu10k1_t *emu, unsigned int voicenum); +void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicenum); +void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum); +void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum); void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum); void snd_emu10k1_voice_clear_loop_stop(emu10k1_t *emu, unsigned int voicenum); void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait); @@ -1112,7 +1182,10 @@ /* GPRs */ #define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ #define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ -#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f */ +#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */ +#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ + /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ + #define C_00000000 0x40 #define C_00000001 0x41 #define C_00000002 0x42 @@ -1154,9 +1227,13 @@ #define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ #define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ -#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f? */ -#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x1f? */ -#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f? */ +#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ +#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ +#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ +#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ +#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ +#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */ +#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */ #define A_GPR(x) (A_FXGPREGBASE + (x)) /* cc_reg constants */ diff -Nru a/include/sound/gus.h b/include/sound/gus.h --- a/include/sound/gus.h 2005-03-03 21:43:46 -08:00 +++ b/include/sound/gus.h 2005-03-03 21:43:46 -08:00 @@ -230,7 +230,7 @@ int mode; /* operation mode */ int client; /* sequencer client number */ int port; /* sequencer port number */ - int midi_has_voices: 1; + unsigned int midi_has_voices: 1; } snd_gus_port_t; typedef struct _snd_gus_voice snd_gus_voice_t; @@ -264,7 +264,7 @@ struct _snd_gus_voice { int number; - int use: 1, + unsigned int use: 1, pcm: 1, synth:1, midi: 1; diff -Nru a/include/sound/hwdep.h b/include/sound/hwdep.h --- a/include/sound/hwdep.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/hwdep.h 2005-03-03 21:43:47 -08:00 @@ -38,6 +38,7 @@ int (*release) (snd_hwdep_t * hw, struct file * file); unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait); int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); + int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma); int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status); int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image); diff -Nru a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h --- a/include/sound/mixer_oss.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/mixer_oss.h 2005-03-03 21:43:47 -08:00 @@ -38,7 +38,7 @@ struct _snd_oss_mixer_slot { int number; - int stereo: 1; + unsigned int stereo: 1; snd_mixer_oss_get_volume_t get_volume; snd_mixer_oss_put_volume_t put_volume; snd_mixer_oss_get_recsrc_t get_recsrc; diff -Nru a/include/sound/rawmidi.h b/include/sound/rawmidi.h --- a/include/sound/rawmidi.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/rawmidi.h 2005-03-03 21:43:47 -08:00 @@ -65,8 +65,7 @@ } snd_rawmidi_global_ops_t; struct _snd_rawmidi_runtime { - unsigned int trigger: 1, /* transfer is running */ - drain: 1, /* drain stage */ + unsigned int drain: 1, /* drain stage */ oss: 1; /* OSS compatible mode */ /* midi stream buffer */ unsigned char *buffer; /* buffer for MIDI data */ diff -Nru a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h --- a/include/sound/seq_virmidi.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/seq_virmidi.h 2005-03-03 21:43:47 -08:00 @@ -38,7 +38,7 @@ int seq_mode; int client; int port; - int trigger: 1; + unsigned int trigger: 1; snd_midi_event_t *parser; snd_seq_event_t event; snd_virmidi_dev_t *rdev; diff -Nru a/include/sound/trident.h b/include/sound/trident.h --- a/include/sound/trident.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/trident.h 2005-03-03 21:43:47 -08:00 @@ -290,7 +290,7 @@ int mode; /* operation mode */ int client; /* sequencer client number */ int port; /* sequencer port number */ - int midi_has_voices: 1; + unsigned int midi_has_voices: 1; } snd_trident_port_t; typedef struct snd_trident_memblk_arg { @@ -308,7 +308,7 @@ struct _snd_trident_voice { unsigned int number; - int use: 1, + unsigned int use: 1, pcm: 1, synth:1, midi: 1; @@ -347,7 +347,7 @@ trident_t *trident; snd_pcm_substream_t *substream; snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */ - int running: 1, + unsigned int running: 1, capture: 1, spdif: 1, foldback: 1, diff -Nru a/include/sound/ymfpci.h b/include/sound/ymfpci.h --- a/include/sound/ymfpci.h 2005-03-03 21:43:47 -08:00 +++ b/include/sound/ymfpci.h 2005-03-03 21:43:47 -08:00 @@ -262,7 +262,7 @@ struct _snd_ymfpci_voice { ymfpci_t *chip; int number; - int use: 1, + unsigned int use: 1, pcm: 1, synth: 1, midi: 1; @@ -288,9 +288,9 @@ snd_ymfpci_pcm_type_t type; snd_pcm_substream_t *substream; ymfpci_voice_t *voices[2]; /* playback only */ - int running: 1; - int output_front: 1; - int output_rear: 1; + unsigned int running: 1; + unsigned int output_front: 1; + unsigned int output_rear: 1; u32 period_size; /* cached from runtime->period_size */ u32 buffer_size; /* cached from runtime->buffer_size */ u32 period_pos; diff -Nru a/include/sound/yss225.h b/include/sound/yss225.h --- a/include/sound/yss225.h 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,23 +0,0 @@ -#ifndef __SOUND_YSS225_H -#define __SOUND_YSS225_H - -extern unsigned char page_zero[256]; -extern unsigned char page_one[256]; -extern unsigned char page_two[128]; -extern unsigned char page_three[128]; -extern unsigned char page_four[128]; -extern unsigned char page_six[192]; -extern unsigned char page_seven[256]; -extern unsigned char page_zero_v2[96]; -extern unsigned char page_one_v2[96]; -extern unsigned char page_two_v2[48]; -extern unsigned char page_three_v2[48]; -extern unsigned char page_four_v2[48]; -extern unsigned char page_seven_v2[96]; -extern unsigned char mod_v2[304]; -extern unsigned char coefficients[364]; -extern unsigned char coefficients2[56]; -extern unsigned char coefficients3[404]; - - -#endif /* __SOUND_YSS225_H */ diff -Nru a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c --- a/sound/arm/sa11xx-uda1341.c 2005-03-03 21:43:47 -08:00 +++ b/sound/arm/sa11xx-uda1341.c 2005-03-03 21:43:47 -08:00 @@ -21,7 +21,7 @@ * merged HAL layer (patches from Brian) */ -/* $Id: sa11xx-uda1341.c,v 1.19 2004/12/15 15:26:10 tiwai Exp $ */ +/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */ /*************************************************************************************************** * @@ -862,7 +862,7 @@ #ifdef CONFIG_PM -static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state) +static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state) { sa11xx_uda1341_t *chip = card->pm_private_data; @@ -878,7 +878,7 @@ return 0; } -static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state) +static int snd_sa11xx_uda1341_resume(snd_card_t *card) { sa11xx_uda1341_t *chip = card->pm_private_data; @@ -938,7 +938,7 @@ if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0) goto nodev; - snd_card_set_dev_pm_callback(card, PM_SYS_DEV, + snd_card_set_generic_pm_callback(card, snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume, sa11xx_uda1341); diff -Nru a/sound/core/Kconfig b/sound/core/Kconfig --- a/sound/core/Kconfig 2005-03-03 21:43:47 -08:00 +++ b/sound/core/Kconfig 2005-03-03 21:43:47 -08:00 @@ -1,16 +1,20 @@ # ALSA soundcard-configuration config SND_TIMER tristate + depends on SND config SND_PCM tristate select SND_TIMER + depends on SND config SND_HWDEP tristate + depends on SND config SND_RAWMIDI tristate + depends on SND config SND_SEQUENCER tristate "Sequencer support" @@ -40,6 +44,7 @@ config SND_OSSEMUL bool + depends on SND config SND_MIXER_OSS tristate "OSS Mixer API" @@ -70,7 +75,7 @@ config SND_SEQUENCER_OSS bool "OSS Sequencer API" - depends on SND_SEQUENCER + depends on SND && SND_SEQUENCER select SND_OSSEMUL help Say Y here to enable OSS sequencer emulation (both @@ -81,20 +86,6 @@ To compile this driver as a module, choose M here: the module will be called snd-seq-oss. -config SND_BIT32_EMUL - tristate "Emulation for 32-bit applications" - depends on SND && COMPAT - select SND_PCM - select SND_RAWMIDI - select SND_TIMER - select SND_HWDEP - help - Say Y here to enable the emulation for 32-bit ALSA-native - applications. - - To compile this driver as a module, choose M here: the module - will be called snd-ioctl32. - config SND_RTCTIMER tristate "RTC Timer support" depends on SND && RTC @@ -137,3 +128,6 @@ Say Y here to enable extra-verbose log messages printed when detecting devices. +config SND_GENERIC_PM + bool + depends on SND diff -Nru a/sound/core/Makefile b/sound/core/Makefile --- a/sound/core/Makefile 2005-03-03 21:43:47 -08:00 +++ b/sound/core/Makefile 2005-03-03 21:43:47 -08:00 @@ -31,4 +31,3 @@ obj-$(CONFIG_SND_OSSEMUL) += oss/ obj-$(CONFIG_SND_SEQUENCER) += seq/ -obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/ diff -Nru a/sound/core/control.c b/sound/core/control.c --- a/sound/core/control.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/control.c 2005-03-03 21:43:47 -08:00 @@ -43,6 +43,9 @@ static DECLARE_RWSEM(snd_ioctl_rwsem); static LIST_HEAD(snd_control_ioctls); +#ifdef CONFIG_COMPAT +static LIST_HEAD(snd_control_compat_ioctls); +#endif static int snd_ctl_open(struct inode *inode, struct file *file) { @@ -595,43 +598,51 @@ return 0; } -static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) +static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info) { snd_card_t *card = ctl->card; - snd_ctl_elem_info_t info; snd_kcontrol_t *kctl; snd_kcontrol_volatile_t *vd; unsigned int index_offset; int result; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &info.id); + kctl = snd_ctl_find_id(card, &info->id); if (kctl == NULL) { up_read(&card->controls_rwsem); return -ENOENT; } #ifdef CONFIG_SND_DEBUG - info.access = 0; + info->access = 0; #endif - result = kctl->info(kctl, &info); + result = kctl->info(kctl, info); if (result >= 0) { - snd_assert(info.access == 0, ); - index_offset = snd_ctl_get_ioff(kctl, &info.id); + snd_assert(info->access == 0, ); + index_offset = snd_ctl_get_ioff(kctl, &info->id); vd = &kctl->vd[index_offset]; - snd_ctl_build_ioff(&info.id, kctl, index_offset); - info.access = vd->access; + snd_ctl_build_ioff(&info->id, kctl, index_offset); + info->access = vd->access; if (vd->owner) { - info.access |= SNDRV_CTL_ELEM_ACCESS_LOCK; + info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; if (vd->owner == ctl) - info.access |= SNDRV_CTL_ELEM_ACCESS_OWNER; - info.owner = vd->owner_pid; + info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; + info->owner = vd->owner_pid; } else { - info.owner = -1; + info->owner = -1; } } up_read(&card->controls_rwsem); + return result; +} + +static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) +{ + snd_ctl_elem_info_t info; + int result; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + result = snd_ctl_elem_info(ctl, &info); if (result >= 0) if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -816,14 +827,6 @@ struct user_element *ue = kcontrol->private_data; *uinfo = ue->info; - if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - uinfo->value.enumerated.items = ue->info.value.enumerated.items; - if (uinfo->value.enumerated.item >= ue->info.value.enumerated.items) - uinfo->value.enumerated.item = 0; - strlcpy(uinfo->value.enumerated.name, - (char *)ue->priv_data + uinfo->value.enumerated.item * 64, - 64); - } return 0; } @@ -851,28 +854,25 @@ kfree(kcontrol->private_data); } -static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) +static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace) { snd_card_t *card = file->card; - snd_ctl_elem_info_t info; snd_kcontrol_t kctl, *_kctl; unsigned int access; - long private_size, extra_size; + long private_size; struct user_element *ue; int idx, err; if (card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - if (info.count > 1024) + if (info->count > 1024) return -EINVAL; - access = info.access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : - (info.access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE)); - info.id.numid = 0; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : + (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE)); + info->id.numid = 0; memset(&kctl, 0, sizeof(kctl)); down_write(&card->controls_rwsem); - _kctl = snd_ctl_find_id(card, &info.id); + _kctl = snd_ctl_find_id(card, &info->id); err = 0; if (_kctl) { if (replace) @@ -886,67 +886,50 @@ up_write(&card->controls_rwsem); if (err < 0) return err; - memcpy(&kctl.id, &info.id, sizeof(info.id)); - kctl.count = info.owner ? info.owner : 1; + memcpy(&kctl.id, &info->id, sizeof(info->id)); + kctl.count = info->owner ? info->owner : 1; access |= SNDRV_CTL_ELEM_ACCESS_USER; kctl.info = snd_ctl_elem_user_info; if (access & SNDRV_CTL_ELEM_ACCESS_READ) kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) kctl.put = snd_ctl_elem_user_put; - extra_size = 0; - switch (info.type) { + switch (info->type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: private_size = sizeof(char); - if (info.count > 128) + if (info->count > 128) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_INTEGER: private_size = sizeof(long); - if (info.count > 128) + if (info->count > 128) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_INTEGER64: private_size = sizeof(long long); - if (info.count > 64) + if (info->count > 64) return -EINVAL; break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - private_size = sizeof(unsigned int); - if (info.count > 128) - return -EINVAL; - if (info.value.enumerated.items > 128) - return -EINVAL; - extra_size = info.value.enumerated.items * 64; - break; case SNDRV_CTL_ELEM_TYPE_BYTES: private_size = sizeof(unsigned char); - if (info.count > 512) + if (info->count > 512) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_IEC958: private_size = sizeof(struct sndrv_aes_iec958); - if (info.count != 1) + if (info->count != 1) return -EINVAL; break; default: return -EINVAL; } - private_size *= info.count; - ue = kcalloc(1, sizeof(struct user_element) + private_size + extra_size, GFP_KERNEL); + private_size *= info->count; + ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL); if (ue == NULL) return -ENOMEM; - ue->info = info; - ue->elem_data = (char *)ue + sizeof(ue); + ue->info = *info; + ue->elem_data = (char *)ue + sizeof(*ue); ue->elem_data_size = private_size; - if (extra_size) { - ue->priv_data = (char *)ue + sizeof(ue) + private_size; - ue->priv_data_size = extra_size; - if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - if (copy_from_user(ue->priv_data, *(char __user **)info.value.enumerated.name, extra_size)) - return -EFAULT; - } - } kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { @@ -969,6 +952,14 @@ return 0; } +static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) +{ + snd_ctl_elem_info_t info; + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + return snd_ctl_elem_add(file, &info, replace); +} + static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id) { snd_ctl_elem_id_t id; @@ -1016,15 +1007,13 @@ switch (power_state) { case SNDRV_CTL_POWER_D0: if (card->power_state != power_state) { - /* FIXME: pass the correct state value */ - card->pm_resume(card, 0); + card->pm_resume(card); snd_power_change_state(card, power_state); } break; case SNDRV_CTL_POWER_D3hot: if (card->power_state != power_state) { - /* FIXME: pass the correct state value */ - card->pm_suspend(card, 0); + card->pm_suspend(card, PMSG_SUSPEND); snd_power_change_state(card, power_state); } break; @@ -1039,8 +1028,7 @@ } #endif -static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_ctl_file_t *ctl; snd_card_t *card; @@ -1061,7 +1049,7 @@ case SNDRV_CTL_IOCTL_ELEM_LIST: return snd_ctl_elem_list(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_INFO: - return snd_ctl_elem_info(ctl, argp); + return snd_ctl_elem_info_user(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_READ: return snd_ctl_elem_read_user(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_WRITE: @@ -1071,9 +1059,9 @@ case SNDRV_CTL_IOCTL_ELEM_UNLOCK: return snd_ctl_elem_unlock(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_ADD: - return snd_ctl_elem_add(ctl, argp, 0); + return snd_ctl_elem_add_user(ctl, argp, 0); case SNDRV_CTL_IOCTL_ELEM_REPLACE: - return snd_ctl_elem_add(ctl, argp, 1); + return snd_ctl_elem_add_user(ctl, argp, 1); case SNDRV_CTL_IOCTL_ELEM_REMOVE: return snd_ctl_elem_remove(ctl, argp); case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: @@ -1113,17 +1101,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_ctl_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset) { snd_ctl_file_t *ctl; @@ -1199,7 +1176,7 @@ * register the device-specific control-ioctls. * called from each device manager like pcm.c, hwdep.c, etc. */ -int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) +static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) { snd_kctl_ioctl_t *pn; @@ -1208,22 +1185,34 @@ return -ENOMEM; pn->fioctl = fcn; down_write(&snd_ioctl_rwsem); - list_add_tail(&pn->list, &snd_control_ioctls); + list_add_tail(&pn->list, lists); up_write(&snd_ioctl_rwsem); return 0; } +int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); +} + +#ifdef CONFIG_COMPAT +int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); +} +#endif + /* * de-register the device-specific control-ioctls. */ -int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) +static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) { struct list_head *list; snd_kctl_ioctl_t *p; snd_runtime_check(fcn != NULL, return -EINVAL); down_write(&snd_ioctl_rwsem); - list_for_each(list, &snd_control_ioctls) { + list_for_each(list, lists) { p = list_entry(list, snd_kctl_ioctl_t, list); if (p->fioctl == fcn) { list_del(&p->list); @@ -1237,6 +1226,19 @@ return -EINVAL; } +int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); +} + +#ifdef CONFIG_COMPAT +int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); +} + +#endif + static int snd_ctl_fasync(int fd, struct file * file, int on) { snd_ctl_file_t *ctl; @@ -1249,6 +1251,15 @@ } /* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "control_compat.c" +#else +#define snd_ctl_ioctl_compat NULL +#endif + +/* * INIT PART */ @@ -1259,7 +1270,8 @@ .open = snd_ctl_open, .release = snd_ctl_release, .poll = snd_ctl_poll, - .ioctl = snd_ctl_ioctl, + .unlocked_ioctl = snd_ctl_ioctl, + .compat_ioctl = snd_ctl_ioctl_compat, .fasync = snd_ctl_fasync, }; diff -Nru a/sound/core/control_compat.c b/sound/core/control_compat.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/core/control_compat.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,412 @@ +/* + * compat ioctls for control API + * + * Copyright (c) by Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* this file included from control.c */ + +#include + +struct sndrv_ctl_elem_list32 { + u32 offset; + u32 space; + u32 used; + u32 count; + u32 pids; + unsigned char reserved[50]; +} /* don't set packed attribute here */; + +static int snd_ctl_elem_list_compat(snd_card_t *card, struct sndrv_ctl_elem_list32 __user *data32) +{ + struct sndrv_ctl_elem_list __user *data; + compat_caddr_t ptr; + int err; + + data = compat_alloc_user_space(sizeof(*data)); + + /* offset, space, used, count */ + if (copy_in_user(data, data32, 4 * sizeof(u32))) + return -EFAULT; + /* pids */ + if (get_user(ptr, &data32->pids) || + put_user(compat_ptr(ptr), &data->pids)) + return -EFAULT; + err = snd_ctl_elem_list(card, data); + if (err < 0) + return err; + /* copy the result */ + if (copy_in_user(data32, data, 4 * sizeof(u32))) + return -EFAULT; + return 0; +} + +/* + * control element info + * it uses union, so the things are not easy.. + */ + +struct sndrv_ctl_elem_info32 { + struct sndrv_ctl_elem_id id; // the size of struct is same + s32 type; + u32 access; + u32 count; + s32 owner; + union { + struct { + s32 min; + s32 max; + s32 step; + } integer; + struct { + u64 min; + u64 max; + u64 step; + } integer64; + struct { + u32 items; + u32 item; + char name[64]; + } enumerated; + unsigned char reserved[128]; + } value; + unsigned char reserved[64]; +} __attribute__((packed)); + +static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_info32 __user *data32) +{ + struct sndrv_ctl_elem_info *data; + int err; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + err = -EFAULT; + /* copy id */ + if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) + goto error; + /* we need to copy the item index. + * hope this doesn't break anything.. + */ + if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) + goto error; + err = snd_ctl_elem_info(ctl, data); + if (err < 0) + goto error; + /* restore info to 32bit */ + err = -EFAULT; + /* id, type, access, count */ + if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) || + copy_to_user(&data32->type, &data->type, 3 * sizeof(u32))) + goto error; + if (put_user(data->owner, &data32->owner)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + case SNDRV_CTL_ELEM_TYPE_INTEGER: + if (put_user(data->value.integer.min, &data32->value.integer.min) || + put_user(data->value.integer.max, &data32->value.integer.max) || + put_user(data->value.integer.step, &data32->value.integer.step)) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_INTEGER64: + if (copy_to_user(&data32->value.integer64, + &data->value.integer64, + sizeof(data->value.integer64))) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + if (copy_to_user(&data32->value.enumerated, + &data->value.enumerated, + sizeof(data->value.enumerated))) + goto error; + break; + default: + break; + } + err = 0; + error: + kfree(data); + return err; +} + +/* read / write */ +struct sndrv_ctl_elem_value32 { + struct sndrv_ctl_elem_id id; + unsigned int indirect; /* bit-field causes misalignment */ + union { + s32 integer[128]; + unsigned char data[512]; +#ifndef CONFIG_X86_64 + s64 integer64[64]; +#endif + } value; + unsigned char reserved[128]; +}; + + +/* get the value type and count of the control */ +static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id, int *countp) +{ + snd_kcontrol_t *kctl; + snd_ctl_elem_info_t info; + int err; + + down_read(&card->controls_rwsem); + kctl = snd_ctl_find_id(card, id); + if (! kctl) { + up_read(&card->controls_rwsem); + return -ENXIO; + } + info.id = *id; + err = kctl->info(kctl, &info); + up_read(&card->controls_rwsem); + if (err >= 0) { + err = info.type; + *countp = info.count; + } + return err; +} + +static int get_elem_size(int type, int count) +{ + switch (type) { + case SNDRV_CTL_ELEM_TYPE_INTEGER64: + return sizeof(s64) * count; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + return sizeof(int) * count; + case SNDRV_CTL_ELEM_TYPE_BYTES: + return 512; + case SNDRV_CTL_ELEM_TYPE_IEC958: + return sizeof(struct sndrv_aes_iec958); + default: + return -1; + } +} + +static int copy_ctl_value_from_user(snd_card_t *card, + struct sndrv_ctl_elem_value *data, + struct sndrv_ctl_elem_value32 __user *data32, + int *typep, int *countp) +{ + int i, type, count, size; + unsigned int indirect; + + if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) + return -EFAULT; + if (get_user(indirect, &data32->indirect)) + return -EFAULT; + if (indirect) + return -EINVAL; + type = get_ctl_type(card, &data->id, &count); + if (type < 0) + return type; + + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || + type == SNDRV_CTL_ELEM_TYPE_INTEGER) { + for (i = 0; i < count; i++) { + int val; + if (get_user(val, &data32->value.integer[i])) + return -EFAULT; + data->value.integer.value[i] = val; + } + } else { + size = get_elem_size(type, count); + if (size < 0) { + printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); + return -EINVAL; + } + if (copy_from_user(data->value.bytes.data, + data32->value.data, size)) + return -EFAULT; + } + + *typep = type; + *countp = count; + return 0; +} + +/* restore the value to 32bit */ +static int copy_ctl_value_to_user(struct sndrv_ctl_elem_value32 __user *data32, + struct sndrv_ctl_elem_value *data, + int type, int count) +{ + int i, size; + + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || + type == SNDRV_CTL_ELEM_TYPE_INTEGER) { + for (i = 0; i < count; i++) { + int val; + val = data->value.integer.value[i]; + if (put_user(val, &data32->value.integer[i])) + return -EFAULT; + } + } else { + size = get_elem_size(type, count); + if (copy_to_user(data32->value.data, + data->value.bytes.data, size)) + return -EFAULT; + } + return 0; +} + +static int snd_ctl_elem_read_user_compat(snd_card_t *card, + struct sndrv_ctl_elem_value32 __user *data32) +{ + struct sndrv_ctl_elem_value *data; + int err, type, count; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) + goto error; + if ((err = snd_ctl_elem_read(card, data)) < 0) + goto error; + err = copy_ctl_value_to_user(data32, data, type, count); + error: + kfree(data); + return err; +} + +static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file, + struct sndrv_ctl_elem_value32 __user *data32) +{ + struct sndrv_ctl_elem_value *data; + int err, type, count; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + if ((err = copy_ctl_value_from_user(file->card, data, data32, &type, &count)) < 0) + goto error; + if ((err = snd_ctl_elem_write(file->card, file, data)) < 0) + goto error; + err = copy_ctl_value_to_user(data32, data, type, count); + error: + kfree(data); + return err; +} + +/* add or replace a user control */ +static int snd_ctl_elem_add_compat(snd_ctl_file_t *file, + struct sndrv_ctl_elem_info32 __user *data32, + int replace) +{ + struct sndrv_ctl_elem_info *data; + int err; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + err = -EFAULT; + /* id, type, access, count */ \ + if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || + copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) + goto error; + if (get_user(data->owner, &data32->owner) || + get_user(data->type, &data32->type)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + case SNDRV_CTL_ELEM_TYPE_INTEGER: + if (get_user(data->value.integer.min, &data32->value.integer.min) || + get_user(data->value.integer.max, &data32->value.integer.max) || + get_user(data->value.integer.step, &data32->value.integer.step)) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_INTEGER64: + if (copy_from_user(&data->value.integer64, + &data32->value.integer64, + sizeof(data->value.integer64))) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + if (copy_from_user(&data->value.enumerated, + &data32->value.enumerated, + sizeof(data->value.enumerated))) + goto error; + break; + default: + break; + } + err = snd_ctl_elem_add(file, data, replace); + error: + kfree(data); + return err; +} + +enum { + SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32), + SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32), + SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32), + SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32), + SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct sndrv_ctl_elem_info32), + SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct sndrv_ctl_elem_info32), +}; + +static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_ctl_file_t *ctl; + struct list_head *list; + void __user *argp = compat_ptr(arg); + int err; + + ctl = file->private_data; + snd_assert(ctl && ctl->card, return -ENXIO); + + switch (cmd) { + case SNDRV_CTL_IOCTL_PVERSION: + case SNDRV_CTL_IOCTL_CARD_INFO: + case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: + case SNDRV_CTL_IOCTL_POWER: + case SNDRV_CTL_IOCTL_POWER_STATE: + case SNDRV_CTL_IOCTL_ELEM_LOCK: + case SNDRV_CTL_IOCTL_ELEM_UNLOCK: + return snd_ctl_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_CTL_IOCTL_ELEM_LIST32: + return snd_ctl_elem_list_compat(ctl->card, argp); + case SNDRV_CTL_IOCTL_ELEM_INFO32: + return snd_ctl_elem_info_compat(ctl, argp); + case SNDRV_CTL_IOCTL_ELEM_READ32: + return snd_ctl_elem_read_user_compat(ctl->card, argp); + case SNDRV_CTL_IOCTL_ELEM_WRITE32: + return snd_ctl_elem_write_user_compat(ctl, argp); + case SNDRV_CTL_IOCTL_ELEM_ADD32: + return snd_ctl_elem_add_compat(ctl, argp, 0); + case SNDRV_CTL_IOCTL_ELEM_REPLACE32: + return snd_ctl_elem_add_compat(ctl, argp, 1); + } + + down_read(&snd_ioctl_rwsem); + list_for_each(list, &snd_control_compat_ioctls) { + snd_kctl_ioctl_t *p = list_entry(list, snd_kctl_ioctl_t, list); + if (p->fioctl) { + err = p->fioctl(ctl->card, ctl, cmd, arg); + if (err != -ENOIOCTLCMD) { + up_read(&snd_ioctl_rwsem); + return err; + } + } + } + up_read(&snd_ioctl_rwsem); + return -ENOIOCTLCMD; +} diff -Nru a/sound/core/hwdep.c b/sound/core/hwdep.c --- a/sound/core/hwdep.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/hwdep.c 2005-03-03 21:43:47 -08:00 @@ -232,8 +232,7 @@ return 0; } -static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) +static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { snd_hwdep_t *hw = file->private_data; void __user *argp = (void __user *)arg; @@ -252,17 +251,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_hwdep_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_hwdep_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma) { snd_hwdep_t *hw = file->private_data; @@ -315,6 +303,12 @@ return -ENOIOCTLCMD; } +#ifdef CONFIG_COMPAT +#include "hwdep_compat.c" +#else +#define snd_hwdep_ioctl_compat NULL +#endif + /* */ @@ -328,7 +322,8 @@ .open = snd_hwdep_open, .release = snd_hwdep_release, .poll = snd_hwdep_poll, - .ioctl = snd_hwdep_ioctl, + .unlocked_ioctl = snd_hwdep_ioctl, + .compat_ioctl = snd_hwdep_ioctl_compat, .mmap = snd_hwdep_mmap, }; @@ -509,12 +504,14 @@ } snd_hwdep_proc_entry = entry; snd_ctl_register_ioctl(snd_hwdep_control_ioctl); + snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl); return 0; } static void __exit alsa_hwdep_exit(void) { snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl); if (snd_hwdep_proc_entry) { snd_info_unregister(snd_hwdep_proc_entry); snd_hwdep_proc_entry = NULL; diff -Nru a/sound/core/hwdep_compat.c b/sound/core/hwdep_compat.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/core/hwdep_compat.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,77 @@ +/* + * 32bit -> 64bit ioctl wrapper for hwdep API + * Copyright (c) by Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file is included from hwdep.c */ + +#include + +struct sndrv_hwdep_dsp_image32 { + u32 index; + unsigned char name[64]; + u32 image; /* pointer */ + u32 length; + u32 driver_data; +} /* don't set packed attribute here */; + +static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw, + struct sndrv_hwdep_dsp_image32 __user *src) +{ + struct sndrv_hwdep_dsp_image *dst; + compat_caddr_t ptr; + u32 val; + + dst = compat_alloc_user_space(sizeof(*dst)); + + /* index and name */ + if (copy_in_user(dst, src, 4 + 64)) + return -EFAULT; + if (get_user(ptr, &src->image) || + put_user(compat_ptr(ptr), &dst->image)) + return -EFAULT; + if (get_user(val, &src->length) || + put_user(val, &dst->length)) + return -EFAULT; + if (get_user(val, &src->driver_data) || + put_user(val, &dst->driver_data)) + return -EFAULT; + + return snd_hwdep_dsp_load(hw, dst); +} + +enum { + SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32) +}; + +static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg) +{ + snd_hwdep_t *hw = file->private_data; + void __user *argp = compat_ptr(arg); + switch (cmd) { + case SNDRV_HWDEP_IOCTL_PVERSION: + case SNDRV_HWDEP_IOCTL_INFO: + case SNDRV_HWDEP_IOCTL_DSP_STATUS: + return snd_hwdep_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_HWDEP_IOCTL_DSP_LOAD32: + return snd_hwdep_dsp_load_compat(hw, argp); + } + if (hw->ops.ioctl_compat) + return hw->ops.ioctl_compat(hw, file, cmd, arg); + return -ENOIOCTLCMD; +} diff -Nru a/sound/core/init.c b/sound/core/init.c --- a/sound/core/init.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/init.c 2005-03-03 21:43:47 -08:00 @@ -39,7 +39,7 @@ unsigned int snd_cards_lock = 0; /* locked for registering/using */ snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; -rwlock_t snd_card_rwlock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(snd_card_rwlock); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag); @@ -84,16 +84,13 @@ write_lock(&snd_card_rwlock); if (idx < 0) { int idx2; - for (idx2 = 0; idx2 < snd_ecards_limit; idx2++) - if (!(snd_cards_lock & (1 << idx2))) { + for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) + if (~snd_cards_lock & idx & 1<= snd_ecards_limit) + snd_ecards_limit = idx + 1; break; } - if (idx < 0 && snd_ecards_limit < SNDRV_CARDS) - /* for dynamically additional devices like hotplug: - * increment the limit if still free slot exists. - */ - idx = snd_ecards_limit++; } else if (idx < snd_ecards_limit) { if (snd_cards_lock & (1 << idx)) err = -ENODEV; /* invalid */ @@ -229,6 +226,10 @@ return 0; } +#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) +static void snd_generic_device_unregister(struct snd_generic_device *dev); +#endif + /** * snd_card_free - frees given soundcard structure * @card: soundcard structure @@ -252,9 +253,9 @@ #ifdef CONFIG_PM wake_up(&card->power_sleep); -#ifdef CONFIG_ISA +#ifdef CONFIG_SND_GENERIC_PM if (card->pm_dev) { - pm_unregister(card->pm_dev); + snd_generic_device_unregister(card->pm_dev); card->pm_dev = NULL; } #endif @@ -374,7 +375,7 @@ while (1) { if (loops-- == 0) { - snd_printk(KERN_ERR "unable to choose default card id (%s)", id); + snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id); strcpy(card->id, card->proc_root->name); return; } @@ -719,8 +720,8 @@ * handler and from the control API. */ int snd_card_set_pm_callback(snd_card_t *card, - int (*suspend)(snd_card_t *, unsigned int), - int (*resume)(snd_card_t *, unsigned int), + int (*suspend)(snd_card_t *, pm_message_t), + int (*resume)(snd_card_t *), void *private_data) { card->pm_suspend = suspend; @@ -729,56 +730,132 @@ return 0; } -static int snd_generic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +#ifdef CONFIG_SND_GENERIC_PM +/* + * use platform_device for generic power-management without a proper bus + * (e.g. ISA) + */ +struct snd_generic_device { + struct platform_device pdev; + snd_card_t *card; +}; + +#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card + +#define SND_GENERIC_NAME "snd_generic_pm" + +static int snd_generic_suspend(struct device *dev, u32 state, u32 level); +static int snd_generic_resume(struct device *dev, u32 level); + +static struct device_driver snd_generic_driver = { + .name = SND_GENERIC_NAME, + .bus = &platform_bus_type, + .suspend = snd_generic_suspend, + .resume = snd_generic_resume, +}; + +static int generic_driver_registered; + +static void generic_driver_unregister(void) +{ + if (generic_driver_registered) { + generic_driver_registered--; + if (! generic_driver_registered) + driver_unregister(&snd_generic_driver); + } +} + +static struct snd_generic_device *snd_generic_device_register(snd_card_t *card) { - snd_card_t *card = dev->data; + struct snd_generic_device *dev; - switch (rqst) { - case PM_SUSPEND: - if (card->power_state == SNDRV_CTL_POWER_D3hot) - break; - /* FIXME: the correct state value? */ - card->pm_suspend(card, 0); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - break; - case PM_RESUME: - if (card->power_state == SNDRV_CTL_POWER_D0) - break; - /* FIXME: the correct state value? */ - card->pm_resume(card, 0); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - break; + if (! generic_driver_registered) { + if (driver_register(&snd_generic_driver) < 0) + return NULL; + } + generic_driver_registered++; + + dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); + if (! dev) { + generic_driver_unregister(); + return NULL; + } + + dev->pdev.name = SND_GENERIC_NAME; + dev->pdev.id = card->number; + dev->card = card; + if (platform_device_register(&dev->pdev) < 0) { + kfree(dev); + generic_driver_unregister(); + return NULL; } + return dev; +} + +static void snd_generic_device_unregister(struct snd_generic_device *dev) +{ + platform_device_unregister(&dev->pdev); + kfree(dev); + generic_driver_unregister(); +} + +/* suspend/resume callbacks for snd_generic platform device */ +static int snd_generic_suspend(struct device *dev, u32 state, u32 level) +{ + snd_card_t *card; + + if (level != SUSPEND_DISABLE) + return 0; + + card = get_snd_generic_card(dev); + if (card->power_state == SNDRV_CTL_POWER_D3hot) + return 0; + card->pm_suspend(card, PMSG_SUSPEND); + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + return 0; +} + +static int snd_generic_resume(struct device *dev, u32 level) +{ + snd_card_t *card; + + if (level != RESUME_ENABLE) + return 0; + + card = get_snd_generic_card(dev); + if (card->power_state == SNDRV_CTL_POWER_D0) + return 0; + card->pm_resume(card); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } /** - * snd_card_set_dev_pm_callback - set the generic power-management callbacks + * snd_card_set_generic_pm_callback - set the generic power-management callbacks * @card: soundcard structure - * @type: PM device type (PM_XXX) * @suspend: suspend callback function * @resume: resume callback function * @private_data: private data to pass to the callback functions * * Registers the power-management and sets the lowlevel callbacks for - * the given card with the given PM type. These callbacks are called - * from the ALSA's common PM handler and from the control API. + * the given card. These callbacks are called from the ALSA's common + * PM handler and from the control API. */ -int snd_card_set_dev_pm_callback(snd_card_t *card, int type, - int (*suspend)(snd_card_t *, unsigned int), - int (*resume)(snd_card_t *, unsigned int), +int snd_card_set_generic_pm_callback(snd_card_t *card, + int (*suspend)(snd_card_t *, pm_message_t), + int (*resume)(snd_card_t *), void *private_data) { - card->pm_dev = pm_register(type, 0, snd_generic_pm_callback); + card->pm_dev = snd_generic_device_register(card); if (! card->pm_dev) return -ENOMEM; - card->pm_dev->data = card; snd_card_set_pm_callback(card, suspend, resume, private_data); return 0; } +#endif /* CONFIG_SND_GENERIC_PM */ #ifdef CONFIG_PCI -int snd_card_pci_suspend(struct pci_dev *dev, u32 state) +int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state) { snd_card_t *card = pci_get_drvdata(dev); int err; @@ -786,8 +863,7 @@ return 0; if (card->power_state == SNDRV_CTL_POWER_D3hot) return 0; - /* FIXME: correct state value? */ - err = card->pm_suspend(card, 0); + err = card->pm_suspend(card, PMSG_SUSPEND); pci_save_state(dev); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return err; @@ -802,8 +878,7 @@ return 0; /* restore the PCI config space */ pci_restore_state(dev); - /* FIXME: correct state value? */ - card->pm_resume(card, 0); + card->pm_resume(card); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } diff -Nru a/sound/core/ioctl32/Makefile b/sound/core/ioctl32/Makefile --- a/sound/core/ioctl32/Makefile 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,11 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 1999 by Jaroslav Kysela -# - -snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o -ifneq ($(CONFIG_SND_SEQUENCER),n) - snd-ioctl32-objs += seq32.o -endif - -obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o diff -Nru a/sound/core/ioctl32/hwdep32.c b/sound/core/ioctl32/hwdep32.c --- a/sound/core/ioctl32/hwdep32.c 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,73 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for hwdep API - * Copyright (c) by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include -#include "ioctl32.h" - -struct sndrv_hwdep_dsp_image32 { - u32 index; - unsigned char name[64]; - u32 image; /* pointer */ - u32 length; - u32 driver_data; -} /* don't set packed attribute here */; - -static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_hwdep_dsp_image __user *data, *dst; - struct sndrv_hwdep_dsp_image32 __user *data32, *src; - compat_caddr_t ptr; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - - /* index and name */ - if (copy_in_user(data, data32, 4 + 64)) - return -EFAULT; - if (__get_user(ptr, &data32->image) || - __put_user(compat_ptr(ptr), &data->image)) - return -EFAULT; - src = data32; - dst = data; - COPY_CVT(length); - COPY_CVT(driver_data); - return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); -} - -DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD); - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32) -}; - -struct ioctl32_mapper hwdep_mappers[] = { - MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO), - MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS), - { SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) }, - { 0 }, -}; diff -Nru a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c --- a/sound/core/ioctl32/ioctl32.c 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,433 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for control API - * Copyright (c) by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ioctl32.h" - - -/* - * register/unregister mappers - * exported for other modules - */ - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("ioctl32 wrapper for ALSA"); -MODULE_LICENSE("GPL"); - -int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); -int unregister_ioctl32_conversion(unsigned int cmd); - - -int snd_ioctl32_register(struct ioctl32_mapper *mappers) -{ - int err; - struct ioctl32_mapper *m; - - for (m = mappers; m->cmd; m++) { - err = register_ioctl32_conversion(m->cmd, m->handler); - if (err >= 0) - m->registered++; - } - return 0; -} - -void snd_ioctl32_unregister(struct ioctl32_mapper *mappers) -{ - struct ioctl32_mapper *m; - - for (m = mappers; m->cmd; m++) { - if (m->registered) { - unregister_ioctl32_conversion(m->cmd); - m->registered = 0; - } - } -} - - -/* - * compatible wrapper - */ -int snd_ioctl32_compat(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp) -{ - if (! filp->f_op || ! filp->f_op->ioctl) - return -ENOTTY; - return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); -} - - -/* - * Controls - */ - -struct sndrv_ctl_elem_list32 { - u32 offset; - u32 space; - u32 used; - u32 count; - u32 pids; - unsigned char reserved[50]; -} /* don't set packed attribute here */; - -static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_ctl_elem_list32 __user *data32; - struct sndrv_ctl_elem_list __user *data; - compat_caddr_t ptr; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - - /* offset, space, used, count */ - if (copy_in_user(data, data32, 4 * sizeof(u32))) - return -EFAULT; - /* pids */ - if (__get_user(ptr, &data32->pids) || - __put_user(compat_ptr(ptr), &data->pids)) - return -EFAULT; - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); - if (err < 0) - return err; - /* copy the result */ - if (copy_in_user(data32, data, 4 * sizeof(u32))) - return -EFAULT; - return 0; -} - -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_list, ctl_elem_list, SNDRV_CTL_IOCTL_ELEM_LIST); - -/* - * control element info - * it uses union, so the things are not easy.. - */ - -struct sndrv_ctl_elem_info32 { - struct sndrv_ctl_elem_id id; // the size of struct is same - s32 type; - u32 access; - u32 count; - s32 owner; - union { - struct { - s32 min; - s32 max; - s32 step; - } integer; - struct { - u64 min; - u64 max; - u64 step; - } integer64; - struct { - u32 items; - u32 item; - char name[64]; - } enumerated; - unsigned char reserved[128]; - } value; - unsigned char reserved[64]; -} __attribute__((packed)); - -static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_ctl_elem_info __user *data, *src; - struct sndrv_ctl_elem_info32 __user *data32, *dst; - unsigned int type; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - - /* copy id */ - if (copy_in_user(&data->id, &data32->id, sizeof(data->id))) - return -EFAULT; - /* we need to copy the item index. - * hope this doesn't break anything.. - */ - if (copy_in_user(&data->value.enumerated.item, - &data32->value.enumerated.item, - sizeof(data->value.enumerated.item))) - return -EFAULT; - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); - if (err < 0) - return err; - /* restore info to 32bit */ - /* for COPY_CVT macro */ - src = data; - dst = data32; - /* id, type, access, count */ - if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) || - copy_in_user(&data32->type, &data->type, 3 * sizeof(u32))) - return -EFAULT; - COPY_CVT(owner); - __get_user(type, &data->type); - switch (type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - COPY_CVT(value.integer.min); - COPY_CVT(value.integer.max); - COPY_CVT(value.integer.step); - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (copy_in_user(&data32->value.integer64, - &data->value.integer64, - sizeof(data->value.integer64))) - return -EFAULT; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (copy_in_user(&data32->value.enumerated, - &data->value.enumerated, - sizeof(data->value.enumerated))) - return -EFAULT; - break; - default: - break; - } - return 0; -} - -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_info, ctl_elem_info, SNDRV_CTL_IOCTL_ELEM_INFO); - -struct sndrv_ctl_elem_value32 { - struct sndrv_ctl_elem_id id; - unsigned int indirect; /* bit-field causes misalignment */ - union { - s32 integer[128]; /* integer and boolean need conversion */ -#ifndef CONFIG_X86_64 - s64 integer64[64]; /* for alignment */ -#endif - unsigned char data[512]; /* others should be compatible */ - } value; - unsigned char reserved[128]; /* not used */ -}; - - -/* hmm, it's so hard to retrieve the value type from the control id.. */ -static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id) -{ - snd_kcontrol_t *kctl; - snd_ctl_elem_info_t info; - int err; - - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, id); - if (! kctl) { - up_read(&card->controls_rwsem); - return -ENXIO; - } - info.id = *id; - err = kctl->info(kctl, &info); - up_read(&card->controls_rwsem); - if (err >= 0) - err = info.type; - return err; -} - -extern int snd_major; - -static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_ctl_elem_value *data; - struct sndrv_ctl_elem_value32 __user *data32; - snd_ctl_file_t *ctl; - int err, i, indirect; - int type; - - /* sanity check */ - if (imajor(file->f_dentry->d_inode) != snd_major || - SNDRV_MINOR_DEVICE(iminor(file->f_dentry->d_inode)) != SNDRV_MINOR_CONTROL) - return -ENOTTY; - - if ((ctl = file->private_data) == NULL) - return -ENOTTY; - - data32 = compat_ptr(arg); - data = kcalloc(1, sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) { - err = -EFAULT; - goto __end; - } - if (__get_user(indirect, &data32->indirect)) { - err = -EFAULT; - goto __end; - } - /* FIXME: indirect access is not supported */ - if (indirect) { - err = -EINVAL; - goto __end; - } - type = get_ctl_type(ctl->card, &data->id); - if (type < 0) { - err = type; - goto __end; - } - - switch (type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - for (i = 0; i < 128; i++) { - int val; - if (__get_user(val, &data32->value.integer[i])) { - err = -EFAULT; - goto __end; - } - data->value.integer.value[i] = val; - } - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - case SNDRV_CTL_ELEM_TYPE_BYTES: - case SNDRV_CTL_ELEM_TYPE_IEC958: - if (__copy_from_user(data->value.bytes.data, - data32->value.data, - sizeof(data32->value.data))) { - err = -EFAULT; - goto __end; - } - break; - default: - printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); - err = -EINVAL; - goto __end; - } - - if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ) - err = snd_ctl_elem_read(ctl->card, data); - else - err = snd_ctl_elem_write(ctl->card, ctl, data); - if (err < 0) - goto __end; - /* restore info to 32bit */ - switch (type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - for (i = 0; i < 128; i++) { - int val; - val = data->value.integer.value[i]; - if (__put_user(val, &data32->value.integer[i])) { - err = -EFAULT; - goto __end; - } - } - break; - default: - if (__copy_to_user(data32->value.data, - data->value.bytes.data, - sizeof(data32->value.data))) { - err = -EFAULT; - goto __end; - } - break; - break; - } - err = 0; - __end: - kfree(data); - return err; -} - -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ); -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_write, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_WRITE); - -/* - */ - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32), - SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32), - SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32), - SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32), -}; - -static struct ioctl32_mapper control_mappers[] = { - /* controls (without rawmidi, hwdep, timer releated ones) */ - MAP_COMPAT(SNDRV_CTL_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_CTL_IOCTL_CARD_INFO), - { SNDRV_CTL_IOCTL_ELEM_LIST32, AP(ctl_elem_list) }, - { SNDRV_CTL_IOCTL_ELEM_INFO32, AP(ctl_elem_info) }, - { SNDRV_CTL_IOCTL_ELEM_READ32, AP(ctl_elem_read) }, - { SNDRV_CTL_IOCTL_ELEM_WRITE32, AP(ctl_elem_write) }, - MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_LOCK), - MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_UNLOCK), - MAP_COMPAT(SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS), - MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_INFO), - MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_INFO), - MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_POWER), - MAP_COMPAT(SNDRV_CTL_IOCTL_POWER_STATE), - { 0 } -}; - - -/* - */ - -extern struct ioctl32_mapper pcm_mappers[]; -extern struct ioctl32_mapper rawmidi_mappers[]; -extern struct ioctl32_mapper timer_mappers[]; -extern struct ioctl32_mapper hwdep_mappers[]; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -extern struct ioctl32_mapper seq_mappers[]; -#endif - -static void snd_ioctl32_done(void) -{ -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - snd_ioctl32_unregister(seq_mappers); -#endif - snd_ioctl32_unregister(hwdep_mappers); - snd_ioctl32_unregister(timer_mappers); - snd_ioctl32_unregister(rawmidi_mappers); - snd_ioctl32_unregister(pcm_mappers); - snd_ioctl32_unregister(control_mappers); -} - -static int __init snd_ioctl32_init(void) -{ - snd_ioctl32_register(control_mappers); - snd_ioctl32_register(pcm_mappers); - snd_ioctl32_register(rawmidi_mappers); - snd_ioctl32_register(timer_mappers); - snd_ioctl32_register(hwdep_mappers); -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - snd_ioctl32_register(seq_mappers); -#endif - return 0; -} - -module_init(snd_ioctl32_init) -module_exit(snd_ioctl32_done) diff -Nru a/sound/core/ioctl32/ioctl32.h b/sound/core/ioctl32/ioctl32.h --- a/sound/core/ioctl32/ioctl32.h 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,102 +0,0 @@ -/* - * 32bit -> 64bit ioctl helpers - * Copyright (c) by Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * This file registers the converters from 32-bit ioctls to 64-bit ones. - * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x) - * macro to a valid 64-bit pointer which is accessible via copy_from/to_user. - * - */ - -#ifndef __ALSA_IOCTL32_H -#define __ALSA_IOCTL32_H - -#include - -#define COPY(x) \ - do { \ - if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \ - return -EFAULT; \ - } while (0) - -#define COPY_ARRAY(x) \ - do { \ - if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \ - return -EFAULT; \ - } while (0) - -#define COPY_CVT(x) \ - do { \ - __typeof__(src->x) __val_tmp; \ - if (get_user(__val_tmp, &src->x) || \ - put_user(__val_tmp, &dst->x))\ - return -EFAULT; \ - } while (0) - -#define convert_from_32(type, dstp, srcp)\ -{\ - struct sndrv_##type __user *dst = dstp;\ - struct sndrv_##type##32 __user *src = srcp;\ - CVT_##sndrv_##type();\ -} - -#define convert_to_32(type, dstp, srcp)\ -{\ - struct sndrv_##type __user *src = srcp;\ - struct sndrv_##type##32 __user *dst = dstp;\ - CVT_##sndrv_##type();\ -} - - -#define DEFINE_ALSA_IOCTL(type) \ -static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\ -{\ - struct sndrv_##type##32 __user *data32;\ - struct sndrv_##type __user *data;\ - int err;\ - data32 = compat_ptr(arg);\ - data = compat_alloc_user_space(sizeof(*data));\ - convert_from_32(type, data, data32);\ - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\ - if (err < 0) \ - return err;\ - if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\ - convert_to_32(type, data32, data);\ - }\ - return 0;\ -} - -#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \ -static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\ - return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\ -} - -#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat } - -struct ioctl32_mapper { - unsigned int cmd; - int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); - int registered; -}; - -int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *); - -int snd_ioctl32_register(struct ioctl32_mapper *mappers); -void snd_ioctl32_unregister(struct ioctl32_mapper *mappers); - -#endif /* __ALSA_IOCTL32_H */ diff -Nru a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c --- a/sound/core/ioctl32/pcm32.c 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,464 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for PCM API - * Copyright (c) by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include -#include -#include "ioctl32.h" - - -/* wrapper for sndrv_pcm_[us]frames */ -struct sndrv_pcm_sframes_str { - sndrv_pcm_sframes_t val; -}; -struct sndrv_pcm_sframes_str32 { - s32 val; -}; -struct sndrv_pcm_uframes_str { - sndrv_pcm_uframes_t val; -}; -struct sndrv_pcm_uframes_str32 { - u32 val; -}; - -#define CVT_sndrv_pcm_sframes_str() { COPY_CVT(val); } -#define CVT_sndrv_pcm_uframes_str() { COPY_CVT(val); } - - -struct sndrv_pcm_hw_params32 { - u32 flags; - struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ - struct sndrv_mask mres[5]; /* reserved masks */ - struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; - struct sndrv_interval ires[9]; /* reserved intervals */ - u32 rmask; - u32 cmask; - u32 info; - u32 msbits; - u32 rate_num; - u32 rate_den; - u32 fifo_size; - unsigned char reserved[64]; -} __attribute__((packed)); - -struct sndrv_pcm_sw_params32 { - s32 tstamp_mode; - u32 period_step; - u32 sleep_min; - u32 avail_min; - u32 xfer_align; - u32 start_threshold; - u32 stop_threshold; - u32 silence_threshold; - u32 silence_size; - u32 boundary; - unsigned char reserved[64]; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_sw_params()\ -{\ - COPY(tstamp_mode);\ - COPY(period_step);\ - COPY(sleep_min);\ - COPY_CVT(avail_min);\ - COPY_CVT(xfer_align);\ - COPY_CVT(start_threshold);\ - COPY_CVT(stop_threshold);\ - COPY_CVT(silence_threshold);\ - COPY_CVT(silence_size);\ - COPY_CVT(boundary);\ -} - -struct sndrv_pcm_channel_info32 { - u32 channel; - u32 offset; - u32 first; - u32 step; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_channel_info()\ -{\ - COPY(channel);\ - COPY_CVT(offset);\ - COPY(first);\ - COPY(step);\ -} - -struct sndrv_pcm_status32 { - s32 state; - struct compat_timespec trigger_tstamp; - struct compat_timespec tstamp; - u32 appl_ptr; - u32 hw_ptr; - s32 delay; - u32 avail; - u32 avail_max; - u32 overrange; - s32 suspended_state; - unsigned char reserved[60]; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_status()\ -{\ - COPY(state);\ - COPY_CVT(trigger_tstamp.tv_sec);\ - COPY_CVT(trigger_tstamp.tv_nsec);\ - COPY_CVT(tstamp.tv_sec);\ - COPY_CVT(tstamp.tv_nsec);\ - COPY_CVT(appl_ptr);\ - COPY_CVT(hw_ptr);\ - COPY_CVT(delay);\ - COPY_CVT(avail);\ - COPY_CVT(avail_max);\ - COPY_CVT(overrange);\ - COPY(suspended_state);\ -} - -DEFINE_ALSA_IOCTL(pcm_uframes_str); -DEFINE_ALSA_IOCTL(pcm_sframes_str); -DEFINE_ALSA_IOCTL(pcm_sw_params); -DEFINE_ALSA_IOCTL(pcm_channel_info); -DEFINE_ALSA_IOCTL(pcm_status); - -/* sanity device check */ -extern int snd_major; -static int sanity_check_pcm(struct file *file) -{ - unsigned short minor; - if (imajor(file->f_dentry->d_inode) != snd_major) - return -ENOTTY; - minor = iminor(file->f_dentry->d_inode); - if (minor >= 256 || - minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) - return -ENOTTY; - return 0; -} - -/* recalcuate the boundary within 32bit */ -static void recalculate_boundary(snd_pcm_runtime_t *runtime) -{ - if (! runtime->buffer_size) - return; - runtime->boundary = runtime->buffer_size; - while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) - runtime->boundary *= 2; -} - -/* both for HW_PARAMS and HW_REFINE */ -static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_pcm_hw_params32 __user *data32; - struct sndrv_pcm_hw_params *data; - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; - int err; - - if (sanity_check_pcm(file)) - return -ENOTTY; - if (! (pcm_file = file->private_data)) - return -ENOTTY; - if (! (substream = pcm_file->substream)) - return -ENOTTY; - if (! (runtime = substream->runtime)) - return -ENOTTY; - - data32 = compat_ptr(arg); - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - if (copy_from_user(data, data32, sizeof(*data32))) { - err = -EFAULT; - goto error; - } - if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE) - err = snd_pcm_hw_refine(substream, data); - else - err = snd_pcm_hw_params(substream, data); - if (err < 0) - goto error; - if (copy_to_user(data32, data, sizeof(*data32)) || - __put_user((u32)data->fifo_size, &data32->fifo_size)) { - err = -EFAULT; - goto error; - } - - if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS) - recalculate_boundary(runtime); - error: - kfree(data); - return err; -} - - -/* - */ -struct sndrv_xferi32 { - s32 result; - u32 buf; - u32 frames; -} __attribute__((packed)); - -static int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_xferi32 data32; - struct sndrv_xferi __user *data; - snd_pcm_sframes_t result; - int err; - - if (copy_from_user(&data32, (void __user *)arg, sizeof(data32))) - return -EFAULT; - data = compat_alloc_user_space(sizeof(*data)); - if (put_user((snd_pcm_sframes_t)data32.result, &data->result) || - __put_user(compat_ptr(data32.buf), &data->buf) || - __put_user((snd_pcm_uframes_t)data32.frames, &data->frames)) - return -EFAULT; - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); - if (err < 0) - return err; - /* copy the result */ - if (__get_user(result, &data->result)) - return -EFAULT; - data32.result = result; - if (copy_to_user((void __user *)arg, &data32, sizeof(data32))) - return -EFAULT; - return 0; -} - - -/* snd_xfern needs remapping of bufs */ -struct sndrv_xfern32 { - s32 result; - u32 bufs; /* this is void **; */ - u32 frames; -} __attribute__((packed)); - -/* - * xfern ioctl nees to copy (up to) 128 pointers on stack. - * although we may pass the copied pointers through f_op->ioctl, but the ioctl - * handler there expands again the same 128 pointers on stack, so it is better - * to handle the function (calling pcm_readv/writev) directly in this handler. - */ -static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; - struct sndrv_xfern32 __user *srcptr = compat_ptr(arg); - struct sndrv_xfern32 data32; - void __user **bufs; - int err = 0, ch, i; - u32 __user *bufptr; - - if (sanity_check_pcm(file)) - return -ENOTTY; - if (! (pcm_file = file->private_data)) - return -ENOTTY; - if (! (substream = pcm_file->substream)) - return -ENOTTY; - if (! substream->runtime) - return -ENOTTY; - - /* check validty of the command */ - switch (native_ctl) { - case SNDRV_PCM_IOCTL_WRITEN_FRAMES: - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) - return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - break; - case SNDRV_PCM_IOCTL_READN_FRAMES: - if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) - return -EINVAL; - break; - } - if ((ch = substream->runtime->channels) > 128) - return -EINVAL; - if (copy_from_user(&data32, (void __user *)arg, sizeof(data32))) - return -EFAULT; - bufptr = compat_ptr(data32.bufs); - bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - for (i = 0; i < ch; i++) { - u32 ptr; - if (get_user(ptr, bufptr)) { - kfree(bufs); - return -EFAULT; - } - bufs[ch] = compat_ptr(ptr); - bufptr++; - } - switch (native_ctl) { - case SNDRV_PCM_IOCTL_WRITEN_FRAMES: - err = snd_pcm_lib_writev(substream, bufs, data32.frames); - break; - case SNDRV_PCM_IOCTL_READN_FRAMES: - err = snd_pcm_lib_readv(substream, bufs, data32.frames); - break; - } - if (err >= 0) { - if (put_user(err, &srcptr->result)) - err = -EFAULT; - } - kfree(bufs); - return err; -} - - -struct sndrv_pcm_mmap_status32 { - s32 state; - s32 pad1; - u32 hw_ptr; - struct compat_timespec tstamp; - s32 suspended_state; -} __attribute__((packed)); - -struct sndrv_pcm_mmap_control32 { - u32 appl_ptr; - u32 avail_min; -} __attribute__((packed)); - -struct sndrv_pcm_sync_ptr32 { - u32 flags; - union { - struct sndrv_pcm_mmap_status32 status; - unsigned char reserved[64]; - } s; - union { - struct sndrv_pcm_mmap_control32 control; - unsigned char reserved[64]; - } c; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_sync_ptr()\ -{\ - COPY(flags);\ - COPY(s.status.state);\ - COPY(s.status.pad1);\ - COPY_CVT(s.status.hw_ptr);\ - COPY_CVT(s.status.tstamp.tv_sec);\ - COPY_CVT(s.status.tstamp.tv_nsec);\ - COPY(s.status.suspended_state);\ - COPY_CVT(c.control.appl_ptr);\ - COPY_CVT(c.control.avail_min);\ -} - -DEFINE_ALSA_IOCTL(pcm_sync_ptr); - -/* - */ - -DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE); -DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS); -DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS); -DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS); -DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY); -DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO); -DEFINE_ALSA_IOCTL_ENTRY(pcm_rewind, pcm_uframes_str, SNDRV_PCM_IOCTL_REWIND); -DEFINE_ALSA_IOCTL_ENTRY(pcm_forward, pcm_uframes_str, SNDRV_PCM_IOCTL_FORWARD); -DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR); - - -/* - * When PCM is used on 32bit mode, we need to disable - * mmap of PCM status/control records because of the size - * incompatibility. - * - * Since INFO ioctl is always called at first, we mark the - * mmap-disabling in this ioctl wrapper. - */ -static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp) -{ - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; - if (! filp->f_op || ! filp->f_op->ioctl) - return -ENOTTY; - pcm_file = filp->private_data; - if (! pcm_file) - return -ENOTTY; - substream = pcm_file->substream; - if (! substream) - return -ENOTTY; - substream->no_mmap_ctrl = 1; - return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); -} - -/* - */ -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32), - SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32), - SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32), - SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32), - SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), - SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32), - SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), - SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32), - SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32), - SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32), - SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32), - SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32), - SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32), - -}; - -struct ioctl32_mapper pcm_mappers[] = { - MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION), - /* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */ - { SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 }, - MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP), - { SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) }, - { SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE), - { SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) }, - { SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) }, - { SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC), - { SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) }, - { SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE), - MAP_COMPAT(SNDRV_PCM_IOCTL_RESET), - MAP_COMPAT(SNDRV_PCM_IOCTL_START), - MAP_COMPAT(SNDRV_PCM_IOCTL_DROP), - MAP_COMPAT(SNDRV_PCM_IOCTL_DRAIN), - MAP_COMPAT(SNDRV_PCM_IOCTL_PAUSE), - { SNDRV_PCM_IOCTL_REWIND32, AP(pcm_rewind) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_RESUME), - MAP_COMPAT(SNDRV_PCM_IOCTL_XRUN), - { SNDRV_PCM_IOCTL_FORWARD32, AP(pcm_forward) }, - { SNDRV_PCM_IOCTL_WRITEI_FRAMES32, AP(pcm_writei) }, - { SNDRV_PCM_IOCTL_READI_FRAMES32, AP(pcm_readi) }, - { SNDRV_PCM_IOCTL_WRITEN_FRAMES32, AP(pcm_writen) }, - { SNDRV_PCM_IOCTL_READN_FRAMES32, AP(pcm_readn) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_LINK), - MAP_COMPAT(SNDRV_PCM_IOCTL_UNLINK), - - { 0 }, -}; diff -Nru a/sound/core/ioctl32/rawmidi32.c b/sound/core/ioctl32/rawmidi32.c --- a/sound/core/ioctl32/rawmidi32.c 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,91 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for raw MIDI API - * Copyright (c) by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include -#include -#include "ioctl32.h" - -struct sndrv_rawmidi_params32 { - s32 stream; - u32 buffer_size; - u32 avail_min; - unsigned int no_active_sensing; /* avoid bit-field */ - unsigned char reserved[16]; -} __attribute__((packed)); - -#define CVT_sndrv_rawmidi_params()\ -{\ - COPY(stream);\ - COPY_CVT(buffer_size);\ - COPY_CVT(avail_min);\ - if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\ - ((size_t __user *)&src->avail_min + 1), 4)) \ - return -EFAULT;\ -} - -struct sndrv_rawmidi_status32 { - s32 stream; - struct compat_timespec tstamp; - u32 avail; - u32 xruns; - unsigned char reserved[16]; -} __attribute__((packed)); - -#define CVT_sndrv_rawmidi_status()\ -{\ - COPY(stream);\ - COPY_CVT(tstamp.tv_sec);\ - COPY_CVT(tstamp.tv_nsec);\ - COPY_CVT(avail);\ - COPY_CVT(xruns);\ -} - -DEFINE_ALSA_IOCTL(rawmidi_params); -DEFINE_ALSA_IOCTL(rawmidi_status); - -DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS); -DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS); - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32), - SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32), -}; - -struct ioctl32_mapper rawmidi_mappers[] = { - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO), - { SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) }, - { SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) }, - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP), - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN), - - MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO), - MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE), - - { 0 }, -}; diff -Nru a/sound/core/ioctl32/seq32.c b/sound/core/ioctl32/seq32.c --- a/sound/core/ioctl32/seq32.c 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,116 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for sequencer API - * Copyright (c) by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include -#include -#include "ioctl32.h" - -struct sndrv_seq_port_info32 { - struct sndrv_seq_addr addr; /* client/port numbers */ - char name[64]; /* port name */ - - u32 capability; /* port capability bits */ - u32 type; /* port type bits */ - s32 midi_channels; /* channels per MIDI port */ - s32 midi_voices; /* voices per MIDI port */ - s32 synth_voices; /* voices per SYNTH port */ - - s32 read_use; /* R/O: subscribers for output (from this port) */ - s32 write_use; /* R/O: subscribers for input (to this port) */ - - u32 kernel; /* reserved for kernel use (must be NULL) */ - u32 flags; /* misc. conditioning */ - unsigned char time_queue; /* queue # for timestamping */ - char reserved[59]; /* for future use */ -}; - -#define CVT_sndrv_seq_port_info()\ -{\ - COPY(addr);\ - COPY_ARRAY(name);\ - COPY(capability);\ - COPY(type);\ - COPY(midi_channels);\ - COPY(midi_voices);\ - COPY(synth_voices);\ - COPY(read_use);\ - COPY(write_use);\ - COPY(flags);\ - COPY(time_queue);\ -} - -DEFINE_ALSA_IOCTL(seq_port_info); -DEFINE_ALSA_IOCTL_ENTRY(create_port, seq_port_info, SNDRV_SEQ_IOCTL_CREATE_PORT); -DEFINE_ALSA_IOCTL_ENTRY(delete_port, seq_port_info, SNDRV_SEQ_IOCTL_DELETE_PORT); -DEFINE_ALSA_IOCTL_ENTRY(get_port_info, seq_port_info, SNDRV_SEQ_IOCTL_GET_PORT_INFO); -DEFINE_ALSA_IOCTL_ENTRY(set_port_info, seq_port_info, SNDRV_SEQ_IOCTL_SET_PORT_INFO); -DEFINE_ALSA_IOCTL_ENTRY(query_next_port, seq_port_info, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT); - -/* - */ -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32), -}; - -struct ioctl32_mapper seq_mappers[] = { - MAP_COMPAT(SNDRV_SEQ_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_SEQ_IOCTL_CLIENT_ID), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SYSTEM_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO), - { SNDRV_SEQ_IOCTL_CREATE_PORT32, AP(create_port) }, - { SNDRV_SEQ_IOCTL_DELETE_PORT32, AP(delete_port) }, - { SNDRV_SEQ_IOCTL_GET_PORT_INFO32, AP(get_port_info) }, - { SNDRV_SEQ_IOCTL_SET_PORT_INFO32, AP(set_port_info) }, - MAP_COMPAT(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_CREATE_QUEUE), - MAP_COMPAT(SNDRV_SEQ_IOCTL_DELETE_QUEUE), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_POOL), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_POOL), - MAP_COMPAT(SNDRV_SEQ_IOCTL_REMOVE_EVENTS), - MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_SUBS), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION), - MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT), - { SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32, AP(query_next_port) }, - MAP_COMPAT(SNDRV_SEQ_IOCTL_RUNNING_MODE), - { 0 }, -}; diff -Nru a/sound/core/ioctl32/timer32.c b/sound/core/ioctl32/timer32.c --- a/sound/core/ioctl32/timer32.c 2005-03-03 21:43:47 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,105 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for timer API - * Copyright (c) by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include -#include -#include "ioctl32.h" - -struct sndrv_timer_info32 { - u32 flags; - s32 card; - unsigned char id[64]; - unsigned char name[80]; - u32 reserved0; - u32 resolution; - unsigned char reserved[64]; -}; - -#define CVT_sndrv_timer_info()\ -{\ - COPY(flags);\ - COPY(card);\ - COPY_ARRAY(id);\ - COPY_ARRAY(name);\ - COPY_CVT(resolution);\ -} - -struct sndrv_timer_status32 { - struct compat_timespec tstamp; - u32 resolution; - u32 lost; - u32 overrun; - u32 queue; - unsigned char reserved[64]; -}; - -#define CVT_sndrv_timer_status()\ -{\ - COPY_CVT(tstamp.tv_sec);\ - COPY_CVT(tstamp.tv_nsec);\ - COPY(resolution);\ - COPY(lost);\ - COPY(overrun);\ - COPY(queue);\ -} - -DEFINE_ALSA_IOCTL(timer_info); -DEFINE_ALSA_IOCTL(timer_status); - -DEFINE_ALSA_IOCTL_ENTRY(timer_info, timer_info, SNDRV_TIMER_IOCTL_INFO); -DEFINE_ALSA_IOCTL_ENTRY(timer_status, timer_status, SNDRV_TIMER_IOCTL_STATUS); - -/* - */ - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32), - SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32), -}; - -struct ioctl32_mapper timer_mappers[] = { - MAP_COMPAT(SNDRV_TIMER_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_TIMER_IOCTL_NEXT_DEVICE), - MAP_COMPAT(SNDRV_TIMER_IOCTL_SELECT), - { SNDRV_TIMER_IOCTL_INFO32, AP(timer_info) }, - MAP_COMPAT(SNDRV_TIMER_IOCTL_PARAMS), - { SNDRV_TIMER_IOCTL_STATUS32, AP(timer_status) }, -#if 0 - /* ** FIXME ** - * The following four entries are disabled because they conflict - * with the TCOC* definitions. - * Unfortunately, the current ioctl32 wrapper uses a single - * hash table for all devices. Once when the wrapper is fixed - * with the table based on devices, they'll be back again. - */ - MAP_COMPAT(SNDRV_TIMER_IOCTL_START), - MAP_COMPAT(SNDRV_TIMER_IOCTL_STOP), - MAP_COMPAT(SNDRV_TIMER_IOCTL_CONTINUE), - MAP_COMPAT(SNDRV_TIMER_IOCTL_PAUSE), -#endif - { 0 }, -}; diff -Nru a/sound/core/memory.c b/sound/core/memory.c --- a/sound/core/memory.c 2005-03-03 21:43:46 -08:00 +++ b/sound/core/memory.c 2005-03-03 21:43:46 -08:00 @@ -50,8 +50,8 @@ static long snd_alloc_vmalloc; static LIST_HEAD(snd_alloc_kmalloc_list); static LIST_HEAD(snd_alloc_vmalloc_list); -static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); +static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock); #define KMALLOC_MAGIC 0x87654321 #define VMALLOC_MAGIC 0x87654320 static snd_info_entry_t *snd_memory_info_entry; diff -Nru a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c --- a/sound/core/oss/mixer_oss.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/oss/mixer_oss.c 2005-03-03 21:43:47 -08:00 @@ -359,16 +359,9 @@ return -ENXIO; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int err; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg); - lock_kernel(); - return err; + return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg); } int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg) @@ -384,6 +377,13 @@ return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); } +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl +#else +#define snd_mixer_oss_ioctl_compat NULL +#endif + /* * REGISTRATION PART */ @@ -393,7 +393,8 @@ .owner = THIS_MODULE, .open = snd_mixer_oss_open, .release = snd_mixer_oss_release, - .ioctl = snd_mixer_oss_ioctl, + .unlocked_ioctl = snd_mixer_oss_ioctl, + .compat_ioctl = snd_mixer_oss_ioctl_compat, }; static snd_minor_t snd_mixer_oss_reg = diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c --- a/sound/core/oss/pcm_oss.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/oss/pcm_oss.c 2005-03-03 21:43:47 -08:00 @@ -636,10 +636,10 @@ if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_write(substream, ptr, frames); + ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_write(substream, ptr, frames); + ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -679,10 +679,10 @@ if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_read(substream, ptr, frames); + ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_read(substream, ptr, frames); + ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); } if (ret == -EPIPE) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { @@ -718,10 +718,10 @@ if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_writev(substream, bufs, frames); + ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_writev(substream, bufs, frames); + ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -758,10 +758,10 @@ if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_readv(substream, bufs, frames); + ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_readv(substream, bufs, frames); + ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -777,7 +777,7 @@ snd_pcm_plugin_channel_t *channels; size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; if (!in_kernel) { - if (copy_from_user(runtime->oss.buffer, buf, bytes)) + if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes)) return -EFAULT; buf = runtime->oss.buffer; } @@ -839,7 +839,7 @@ return xfer > 0 ? xfer : -EAGAIN; } } else { - tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0); + tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0); if (tmp <= 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; runtime->oss.bytes += tmp; @@ -858,7 +858,7 @@ { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_sframes_t frames, frames1; - char *final_dst = buf; + char __user *final_dst = (char __user *)buf; if (runtime->oss.plugin_first) { snd_pcm_plugin_channel_t *channels; size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; @@ -1058,6 +1058,7 @@ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { size = (runtime->frame_bits * size) / 8; while (size > 0) { + mm_segment_t fs; size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; size -= size1; size1 *= 8; @@ -1065,7 +1066,9 @@ snd_pcm_format_set_silence(runtime->format, runtime->oss.buffer, size1); - snd_pcm_lib_write(substream, runtime->oss.buffer, size1); + fs = snd_enter_user(); + snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1); + snd_leave_user(fs); } } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { void __user *buffers[runtime->channels]; @@ -1913,8 +1916,7 @@ return 0; } -static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_oss_file_t *pcm_oss_file; int __user *p = (int __user *)arg; @@ -2073,16 +2075,12 @@ return -EINVAL; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_pcm_oss_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl +#else +#define snd_pcm_oss_ioctl_compat NULL +#endif static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -2410,7 +2408,8 @@ .open = snd_pcm_oss_open, .release = snd_pcm_oss_release, .poll = snd_pcm_oss_poll, - .ioctl = snd_pcm_oss_ioctl, + .unlocked_ioctl = snd_pcm_oss_ioctl, + .compat_ioctl = snd_pcm_oss_ioctl_compat, .mmap = snd_pcm_oss_mmap, }; diff -Nru a/sound/core/pcm.c b/sound/core/pcm.c --- a/sound/core/pcm.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/pcm.c 2005-03-03 21:43:47 -08:00 @@ -1004,6 +1004,7 @@ snd_info_entry_t *entry; snd_ctl_register_ioctl(snd_pcm_control_ioctl); + snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl); if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read); if (snd_info_register(entry) < 0) { @@ -1018,6 +1019,7 @@ static void __exit alsa_pcm_exit(void) { snd_ctl_unregister_ioctl(snd_pcm_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl); if (snd_pcm_proc_entry) { snd_info_unregister(snd_pcm_proc_entry); snd_pcm_proc_entry = NULL; diff -Nru a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/core/pcm_compat.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,513 @@ +/* + * 32bit -> 64bit ioctl wrapper for PCM API + * Copyright (c) by Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from pcm_native.c */ + +#include + +static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream, + s32 __user *src) +{ + snd_pcm_sframes_t delay; + mm_segment_t fs; + int err; + + fs = snd_enter_user(); + err = snd_pcm_delay(substream, &delay); + snd_leave_user(fs); + if (err < 0) + return err; + if (put_user(delay, src)) + return -EFAULT; + return err; +} + +static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream, + u32 __user *src) +{ + snd_pcm_uframes_t frames; + int err; + + if (get_user(frames, src)) + return -EFAULT; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_playback_rewind(substream, frames); + else + err = snd_pcm_capture_rewind(substream, frames); + if (put_user(err, src)) + return -EFAULT; + return err < 0 ? err : 0; +} + +static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream, + u32 __user *src) +{ + snd_pcm_uframes_t frames; + int err; + + if (get_user(frames, src)) + return -EFAULT; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_playback_forward(substream, frames); + else + err = snd_pcm_capture_forward(substream, frames); + if (put_user(err, src)) + return -EFAULT; + return err < 0 ? err : 0; +} + +struct sndrv_pcm_hw_params32 { + u32 flags; + struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ + struct sndrv_mask mres[5]; /* reserved masks */ + struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; + struct sndrv_interval ires[9]; /* reserved intervals */ + u32 rmask; + u32 cmask; + u32 info; + u32 msbits; + u32 rate_num; + u32 rate_den; + u32 fifo_size; + unsigned char reserved[64]; +}; + +struct sndrv_pcm_sw_params32 { + s32 tstamp_mode; + u32 period_step; + u32 sleep_min; + u32 avail_min; + u32 xfer_align; + u32 start_threshold; + u32 stop_threshold; + u32 silence_threshold; + u32 silence_size; + u32 boundary; + unsigned char reserved[64]; +}; + +static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_sw_params32 __user *src) +{ + snd_pcm_sw_params_t params; + int err; + + memset(¶ms, 0, sizeof(params)); + if (get_user(params.tstamp_mode, &src->tstamp_mode) || + get_user(params.period_step, &src->period_step) || + get_user(params.sleep_min, &src->sleep_min) || + get_user(params.avail_min, &src->avail_min) || + get_user(params.xfer_align, &src->xfer_align) || + get_user(params.start_threshold, &src->start_threshold) || + get_user(params.stop_threshold, &src->stop_threshold) || + get_user(params.silence_threshold, &src->silence_threshold) || + get_user(params.silence_size, &src->silence_size)) + return -EFAULT; + err = snd_pcm_sw_params(substream, ¶ms); + if (err < 0) + return err; + if (put_user(params.boundary, &src->boundary)) + return -EFAULT; + return err; +} + +struct sndrv_pcm_channel_info32 { + u32 channel; + u32 offset; + u32 first; + u32 step; +}; + +static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_channel_info32 __user *src) +{ + snd_pcm_channel_info_t info; + int err; + + if (get_user(info.channel, &src->channel) || + get_user(info.offset, &src->offset) || + get_user(info.first, &src->first) || + get_user(info.step, &src->step)) + return -EFAULT; + err = snd_pcm_channel_info(substream, &info); + if (err < 0) + return err; + if (put_user(info.channel, &src->channel) || + put_user(info.offset, &src->offset) || + put_user(info.first, &src->first) || + put_user(info.step, &src->step)) + return -EFAULT; + return err; +} + +struct sndrv_pcm_status32 { + s32 state; + struct compat_timespec trigger_tstamp; + struct compat_timespec tstamp; + u32 appl_ptr; + u32 hw_ptr; + s32 delay; + u32 avail; + u32 avail_max; + u32 overrange; + s32 suspended_state; + unsigned char reserved[60]; +} __attribute__((packed)); + + +static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_status32 __user *src) +{ + snd_pcm_status_t status; + int err; + + err = snd_pcm_status(substream, &status); + if (err < 0) + return err; + + if (put_user(status.state, &src->state) || + put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) || + put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) || + put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + put_user(status.appl_ptr, &src->appl_ptr) || + put_user(status.hw_ptr, &src->hw_ptr) || + put_user(status.delay, &src->delay) || + put_user(status.avail, &src->avail) || + put_user(status.avail_max, &src->avail_max) || + put_user(status.overrange, &src->overrange) || + put_user(status.suspended_state, &src->suspended_state)) + return -EFAULT; + + return err; +} + +/* recalcuate the boundary within 32bit */ +static void recalculate_boundary(snd_pcm_runtime_t *runtime) +{ + if (! runtime->buffer_size) + return; + runtime->boundary = runtime->buffer_size; + while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) + runtime->boundary *= 2; +} + +/* both for HW_PARAMS and HW_REFINE */ +static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, + int refine, + struct sndrv_pcm_hw_params32 __user *data32) +{ + struct sndrv_pcm_hw_params *data; + snd_pcm_runtime_t *runtime; + int err; + + if (! (runtime = substream->runtime)) + return -ENOTTY; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + /* only fifo_size is different, so just copy all */ + if (copy_from_user(data, data32, sizeof(*data32))) { + err = -EFAULT; + goto error; + } + if (refine) + err = snd_pcm_hw_refine(substream, data); + else + err = snd_pcm_hw_params(substream, data); + if (err < 0) + goto error; + if (copy_to_user(data32, data, sizeof(*data32)) || + put_user(data->fifo_size, &data32->fifo_size)) { + err = -EFAULT; + goto error; + } + + if (! refine) + recalculate_boundary(runtime); + error: + kfree(data); + return err; +} + + +/* + */ +struct sndrv_xferi32 { + s32 result; + u32 buf; + u32 frames; +}; + +static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream, + int dir, struct sndrv_xferi32 __user *data32) +{ + compat_caddr_t buf; + u32 frames; + int err; + + if (! substream->runtime) + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + + if (get_user(buf, &data32->buf) || + get_user(frames, &data32->frames)) + return -EFAULT; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_lib_write(substream, compat_ptr(buf), frames); + else + err = snd_pcm_lib_read(substream, compat_ptr(buf), frames); + if (err < 0) + return err; + /* copy the result */ + if (put_user(err, &data32->result)) + return -EFAULT; + return 0; +} + + +/* snd_xfern needs remapping of bufs */ +struct sndrv_xfern32 { + s32 result; + u32 bufs; /* this is void **; */ + u32 frames; +}; + +/* + * xfern ioctl nees to copy (up to) 128 pointers on stack. + * although we may pass the copied pointers through f_op->ioctl, but the ioctl + * handler there expands again the same 128 pointers on stack, so it is better + * to handle the function (calling pcm_readv/writev) directly in this handler. + */ +static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream, + int dir, struct sndrv_xfern32 __user *data32) +{ + compat_caddr_t buf; + compat_caddr_t __user *bufptr; + u32 frames; + void __user **bufs; + int err, ch, i; + + if (! substream->runtime) + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; + + if ((ch = substream->runtime->channels) > 128) + return -EINVAL; + if (get_user(buf, &data32->bufs) || + get_user(frames, &data32->frames)) + return -EFAULT; + bufptr = compat_ptr(buf); + bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL); + if (bufs == NULL) + return -ENOMEM; + for (i = 0; i < ch; i++) { + u32 ptr; + if (get_user(ptr, bufptr)) { + kfree(bufs); + return -EFAULT; + } + bufs[ch] = compat_ptr(ptr); + bufptr++; + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_lib_writev(substream, bufs, frames); + else + err = snd_pcm_lib_readv(substream, bufs, frames); + if (err >= 0) { + if (put_user(err, &data32->result)) + err = -EFAULT; + } + kfree(bufs); + return err; +} + + +struct sndrv_pcm_mmap_status32 { + s32 state; + s32 pad1; + u32 hw_ptr; + struct compat_timespec tstamp; + s32 suspended_state; +} __attribute__((packed)); + +struct sndrv_pcm_mmap_control32 { + u32 appl_ptr; + u32 avail_min; +}; + +struct sndrv_pcm_sync_ptr32 { + u32 flags; + union { + struct sndrv_pcm_mmap_status32 status; + unsigned char reserved[64]; + } s; + union { + struct sndrv_pcm_mmap_control32 control; + unsigned char reserved[64]; + } c; +} __attribute__((packed)); + +static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_sync_ptr32 __user *src) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + volatile struct sndrv_pcm_mmap_status *status; + volatile struct sndrv_pcm_mmap_control *control; + u32 sflags; + struct sndrv_pcm_mmap_control scontrol; + struct sndrv_pcm_mmap_status sstatus; + int err; + + snd_assert(runtime, return -EINVAL); + + if (get_user(sflags, &src->flags) || + get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || + get_user(scontrol.avail_min, &src->c.control.avail_min)) + return -EFAULT; + if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { + err = snd_pcm_hwsync(substream); + if (err < 0) + return err; + } + status = runtime->status; + control = runtime->control; + snd_pcm_stream_lock_irq(substream); + if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) + control->appl_ptr = scontrol.appl_ptr; + else + scontrol.appl_ptr = control->appl_ptr; + if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) + control->avail_min = scontrol.avail_min; + else + scontrol.avail_min = control->avail_min; + sstatus.state = status->state; + sstatus.hw_ptr = status->hw_ptr; + sstatus.tstamp = status->tstamp; + sstatus.suspended_state = status->suspended_state; + snd_pcm_stream_unlock_irq(substream); + if (put_user(sstatus.state, &src->s.status.state) || + put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || + put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) || + put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) || + put_user(sstatus.suspended_state, &src->s.status.suspended_state) || + put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || + put_user(scontrol.avail_min, &src->c.control.avail_min)) + return -EFAULT; + + return 0; +} + + +/* + */ +enum { + SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32), + SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32), + SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32), + SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32), + SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), + SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32), + SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), + SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32), + SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32), + SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32), + SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32), + SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32), + SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32), + +}; + +static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_pcm_file_t *pcm_file; + snd_pcm_substream_t *substream; + void __user *argp = compat_ptr(arg); + + pcm_file = file->private_data; + if (! pcm_file) + return -ENOTTY; + substream = pcm_file->substream; + if (! substream) + return -ENOTTY; + + /* + * When PCM is used on 32bit mode, we need to disable + * mmap of PCM status/control records because of the size + * incompatibility. + */ + substream->no_mmap_ctrl = 1; + + switch (cmd) { + case SNDRV_PCM_IOCTL_PVERSION: + case SNDRV_PCM_IOCTL_INFO: + case SNDRV_PCM_IOCTL_TSTAMP: + case SNDRV_PCM_IOCTL_HWSYNC: + case SNDRV_PCM_IOCTL_PREPARE: + case SNDRV_PCM_IOCTL_RESET: + case SNDRV_PCM_IOCTL_START: + case SNDRV_PCM_IOCTL_DROP: + case SNDRV_PCM_IOCTL_DRAIN: + case SNDRV_PCM_IOCTL_PAUSE: + case SNDRV_PCM_IOCTL_HW_FREE: + case SNDRV_PCM_IOCTL_RESUME: + case SNDRV_PCM_IOCTL_XRUN: + case SNDRV_PCM_IOCTL_LINK: + case SNDRV_PCM_IOCTL_UNLINK: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return snd_pcm_playback_ioctl1(substream, cmd, argp); + else + return snd_pcm_capture_ioctl1(substream, cmd, argp); + case SNDRV_PCM_IOCTL_HW_REFINE32: + return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); + case SNDRV_PCM_IOCTL_HW_PARAMS32: + return snd_pcm_ioctl_hw_params_compat(substream, 0, argp); + case SNDRV_PCM_IOCTL_SW_PARAMS32: + return snd_pcm_ioctl_sw_params_compat(substream, argp); + case SNDRV_PCM_IOCTL_STATUS32: + return snd_pcm_status_user_compat(substream, argp); + case SNDRV_PCM_IOCTL_SYNC_PTR32: + return snd_pcm_ioctl_sync_ptr_compat(substream, argp); + case SNDRV_PCM_IOCTL_CHANNEL_INFO32: + return snd_pcm_ioctl_channel_info_compat(substream, argp); + case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: + return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); + case SNDRV_PCM_IOCTL_READI_FRAMES32: + return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); + case SNDRV_PCM_IOCTL_WRITEN_FRAMES32: + return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); + case SNDRV_PCM_IOCTL_READN_FRAMES32: + return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); + case SNDRV_PCM_IOCTL_DELAY32: + return snd_pcm_ioctl_delay_compat(substream, argp); + case SNDRV_PCM_IOCTL_REWIND32: + return snd_pcm_ioctl_rewind_compat(substream, argp); + case SNDRV_PCM_IOCTL_FORWARD32: + return snd_pcm_ioctl_forward_compat(substream, argp); + } + + return -ENOIOCTLCMD; +} diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c --- a/sound/core/pcm_memory.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/pcm_memory.c 2005-03-03 21:43:47 -08:00 @@ -291,7 +291,7 @@ * @substream: the substream to allocate the DMA buffer to * @size: the requested buffer size in bytes * - * Allocates the DMA buffer on the BUS type given by + * Allocates the DMA buffer on the BUS type given earlier to * snd_pcm_lib_preallocate_xxx_pages(). * * Returns 1 if the buffer is changed, 0 if not changed, or a negative diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c --- a/sound/core/pcm_native.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/pcm_native.c 2005-03-03 21:43:47 -08:00 @@ -65,7 +65,7 @@ * */ -rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(snd_pcm_link_rwlock); static DECLARE_RWSEM(snd_pcm_link_rwsem); @@ -602,17 +602,13 @@ return 0; } -static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info) { - snd_pcm_channel_info_t info; snd_pcm_runtime_t *runtime; - int res; unsigned int channel; snd_assert(substream != NULL, return -ENXIO); - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - channel = info.channel; + channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { @@ -622,9 +618,19 @@ snd_pcm_stream_unlock_irq(substream); if (channel >= runtime->channels) return -EINVAL; - memset(&info, 0, sizeof(info)); - info.channel = channel; - res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info); + memset(info, 0, sizeof(*info)); + info->channel = channel; + return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info); +} + +static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +{ + snd_pcm_channel_info_t info; + int res; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + res = snd_pcm_channel_info(substream, &info); if (res < 0) return res; if (copy_to_user(_info, &info, sizeof(info))) @@ -2440,7 +2446,7 @@ case SNDRV_PCM_IOCTL_STATUS: return snd_pcm_status_user(substream, arg); case SNDRV_PCM_IOCTL_CHANNEL_INFO: - return snd_pcm_channel_info(substream, arg); + return snd_pcm_channel_info_user(substream, arg); case SNDRV_PCM_IOCTL_PREPARE: return snd_pcm_prepare(substream); case SNDRV_PCM_IOCTL_RESET: @@ -2640,40 +2646,28 @@ return snd_pcm_common_ioctl1(substream, cmd, arg); } -static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } -static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, @@ -2683,7 +2677,7 @@ int result; fs = snd_enter_user(); - result = snd_pcm_playback_ioctl1(substream, cmd, arg); + result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -2695,7 +2689,7 @@ int result; fs = snd_enter_user(); - result = snd_pcm_capture_ioctl1(substream, cmd, arg); + result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -3198,6 +3192,15 @@ } /* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "pcm_compat.c" +#else +#define snd_pcm_ioctl_compat NULL +#endif + +/* * To be removed helpers to keep binary compatibility */ @@ -3318,7 +3321,8 @@ .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_playback_poll, - .ioctl = snd_pcm_playback_ioctl, + .unlocked_ioctl = snd_pcm_playback_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; @@ -3330,7 +3334,8 @@ .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_capture_poll, - .ioctl = snd_pcm_capture_ioctl, + .unlocked_ioctl = snd_pcm_capture_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; diff -Nru a/sound/core/rawmidi.c b/sound/core/rawmidi.c --- a/sound/core/rawmidi.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/rawmidi.c 2005-03-03 21:43:47 -08:00 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -115,7 +117,6 @@ snd_rawmidi_runtime_t *runtime = substream->runtime; substream->ops->trigger(substream, 0); - runtime->trigger = 0; runtime->drain = 0; /* interrupts are not enabled at this moment, so spinlock is not required */ @@ -132,27 +133,22 @@ err = 0; runtime->drain = 1; - while (runtime->avail < runtime->buffer_size) { - timeout = interruptible_sleep_on_timeout(&runtime->sleep, 10 * HZ); - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - if (runtime->avail < runtime->buffer_size && !timeout) { - snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); - err = -EIO; - break; - } + timeout = wait_event_interruptible_timeout(runtime->sleep, + (runtime->avail >= runtime->buffer_size), + 10*HZ); + if (signal_pending(current)) + err = -ERESTARTSYS; + if (runtime->avail < runtime->buffer_size && !timeout) { + snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); + err = -EIO; } runtime->drain = 0; if (err != -ERESTARTSYS) { /* we need wait a while to make sure that Tx FIFOs are empty */ if (substream->ops->drain) substream->ops->drain(substream); - else { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 20); - } + else + msleep(50); snd_rawmidi_drop_output(substream); } return err; @@ -163,7 +159,6 @@ snd_rawmidi_runtime_t *runtime = substream->runtime; substream->ops->trigger(substream, 0); - runtime->trigger = 0; runtime->drain = 0; /* interrupts aren't enabled at this moment, so spinlock isn't needed */ runtime->appl_ptr = runtime->hw_ptr = 0; @@ -465,7 +460,6 @@ substream = rfile->input; rfile->input = NULL; runtime = substream->runtime; - runtime->trigger = 0; substream->ops->trigger(substream, 0); substream->ops->close(substream); snd_rawmidi_done_buffer(runtime); @@ -673,8 +667,7 @@ return 0; } -static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_rawmidi_file_t *rfile; void __user *argp = (void __user *)arg; @@ -784,17 +777,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_rawmidi_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_rawmidi_control_ioctl(snd_card_t * card, snd_ctl_file_t * control, unsigned int cmd, @@ -887,7 +869,7 @@ count1 = count; if (count1 > (int)(runtime->buffer_size - runtime->avail)) { count1 = runtime->buffer_size - runtime->avail; - runtime->xruns = count - count1; + runtime->xruns += count - count1; } if (count1 > 0) { memcpy(runtime->buffer, buffer, count1); @@ -925,7 +907,8 @@ memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1); } else { spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_to_user(buf + result, runtime->buffer + runtime->appl_ptr, count1)) { + if (copy_to_user((char __user *)buf + result, + runtime->buffer + runtime->appl_ptr, count1)) { return result > 0 ? result : -EFAULT; } spin_lock_irqsave(&runtime->lock, flags); @@ -942,7 +925,6 @@ long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count) { - substream->runtime->trigger = 1; substream->ops->trigger(substream, 1); return snd_rawmidi_kernel_read1(substream, buf, count, 1); } @@ -960,7 +942,6 @@ if (substream == NULL) return -EIO; runtime = substream->runtime; - runtime->trigger = 1; substream->ops->trigger(substream, 1); result = 0; while (count > 0) { @@ -984,7 +965,7 @@ spin_lock_irq(&runtime->lock); } spin_unlock_irq(&runtime->lock); - count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0); + count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0); if (count1 < 0) return result > 0 ? result : count1; result += count1; @@ -1012,8 +993,6 @@ } spin_lock_irqsave(&runtime->lock, flags); result = runtime->avail >= runtime->buffer_size; - if (result) - runtime->trigger = 1; spin_unlock_irqrestore(&runtime->lock, flags); return result; } @@ -1046,7 +1025,6 @@ spin_lock_irqsave(&runtime->lock, flags); if (runtime->avail >= runtime->buffer_size) { /* warning: lowlevel layer MUST trigger down the hardware */ - runtime->trigger = 0; goto __skip; } if (count == 1) { /* special case, faster code */ @@ -1061,8 +1039,12 @@ memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1); count -= count1; result += count1; - if (count > 0) + if (count > 0) { + if (count > (int)(runtime->buffer_size - runtime->avail - count1)) + count = runtime->buffer_size - runtime->avail - count1; memcpy(buffer + count1, runtime->buffer, count); + result += count; + } } __skip: spin_unlock_irqrestore(&runtime->lock, flags); @@ -1152,7 +1134,8 @@ memcpy(runtime->buffer + runtime->appl_ptr, buf, count1); } else { spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_from_user(runtime->buffer + runtime->appl_ptr, buf, count1)) { + if (copy_from_user(runtime->buffer + runtime->appl_ptr, + (char __user *)buf, count1)) { spin_lock_irqsave(&runtime->lock, flags); result = result > 0 ? result : -EFAULT; goto __end; @@ -1167,8 +1150,6 @@ count -= count1; } __end: - if (result > 0) - runtime->trigger = 1; count1 = runtime->avail < runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); if (count1) @@ -1217,7 +1198,7 @@ spin_lock_irq(&runtime->lock); } spin_unlock_irq(&runtime->lock); - count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0); + count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0); if (count1 < 0) return result > 0 ? result : count1; result += count1; @@ -1257,7 +1238,6 @@ rfile = file->private_data; if (rfile->input != NULL) { runtime = rfile->input->runtime; - runtime->trigger = 1; rfile->input->ops->trigger(rfile->input, 1); poll_wait(file, &runtime->sleep, wait); } @@ -1278,6 +1258,14 @@ } /* + */ +#ifdef CONFIG_COMPAT +#include "rawmidi_compat.c" +#else +#define snd_rawmidi_ioctl_compat NULL +#endif + +/* */ @@ -1347,7 +1335,8 @@ .open = snd_rawmidi_open, .release = snd_rawmidi_release, .poll = snd_rawmidi_poll, - .ioctl = snd_rawmidi_ioctl, + .unlocked_ioctl = snd_rawmidi_ioctl, + .compat_ioctl = snd_rawmidi_ioctl_compat, }; static snd_minor_t snd_rawmidi_reg = @@ -1628,6 +1617,7 @@ { snd_ctl_register_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl); #ifdef CONFIG_SND_OSSEMUL { int i; /* check device map table */ @@ -1649,6 +1639,7 @@ static void __exit alsa_rawmidi_exit(void) { snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl); } module_init(alsa_rawmidi_init) diff -Nru a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/core/rawmidi_compat.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,120 @@ +/* + * 32bit -> 64bit ioctl wrapper for raw MIDI API + * Copyright (c) by Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from rawmidi.c */ + +#include + +struct sndrv_rawmidi_params32 { + s32 stream; + u32 buffer_size; + u32 avail_min; + unsigned int no_active_sensing; /* avoid bit-field */ + unsigned char reserved[16]; +} __attribute__((packed)); + +static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile, + struct sndrv_rawmidi_params32 __user *src) +{ + snd_rawmidi_params_t params; + unsigned int val; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(params.stream, &src->stream) || + get_user(params.buffer_size, &src->buffer_size) || + get_user(params.avail_min, &src->avail_min) || + get_user(val, &src->no_active_sensing)) + return -EFAULT; + params.no_active_sensing = val; + switch (params.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + return snd_rawmidi_output_params(rfile->output, ¶ms); + case SNDRV_RAWMIDI_STREAM_INPUT: + return snd_rawmidi_input_params(rfile->input, ¶ms); + } + return -EINVAL; +} + +struct sndrv_rawmidi_status32 { + s32 stream; + struct compat_timespec tstamp; + u32 avail; + u32 xruns; + unsigned char reserved[16]; +} __attribute__((packed)); + +static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile, + struct sndrv_rawmidi_status32 __user *src) +{ + int err; + snd_rawmidi_status_t status; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(status.stream, &src->stream)) + return -EFAULT; + + switch (status.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + err = snd_rawmidi_output_status(rfile->output, &status); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: + err = snd_rawmidi_input_status(rfile->input, &status); + break; + default: + return -EINVAL; + } + if (err < 0) + return err; + + if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + put_user(status.avail, &src->avail) || + put_user(status.xruns, &src->xruns)) + return -EFAULT; + + return 0; +} + +enum { + SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32), + SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32), +}; + +static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_rawmidi_file_t *rfile; + void __user *argp = compat_ptr(arg); + + rfile = file->private_data; + switch (cmd) { + case SNDRV_RAWMIDI_IOCTL_PVERSION: + case SNDRV_RAWMIDI_IOCTL_INFO: + case SNDRV_RAWMIDI_IOCTL_DROP: + case SNDRV_RAWMIDI_IOCTL_DRAIN: + return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_RAWMIDI_IOCTL_PARAMS32: + return snd_rawmidi_ioctl_params_compat(rfile, argp); + case SNDRV_RAWMIDI_IOCTL_STATUS32: + return snd_rawmidi_ioctl_status_compat(rfile, argp); + } + return -ENOIOCTLCMD; +} diff -Nru a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c --- a/sound/core/seq/oss/seq_oss.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/oss/seq_oss.c 2005-03-03 21:43:47 -08:00 @@ -59,7 +59,7 @@ static int odev_release(struct inode *inode, struct file *file); static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset); static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); -static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static unsigned int odev_poll(struct file *file, poll_table * wait); #ifdef CONFIG_PROC_FS static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf); @@ -177,20 +177,20 @@ return snd_seq_oss_write(dp, buf, count, file); } -static int -odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long +odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { seq_oss_devinfo_t *dp; - int err; dp = file->private_data; snd_assert(dp != NULL, return -EIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_oss_ioctl(dp, cmd, arg); - lock_kernel(); - return err; + return snd_seq_oss_ioctl(dp, cmd, arg); } +#ifdef CONFIG_COMPAT +#define odev_ioctl_compat odev_ioctl +#else +#define odev_ioctl_compat NULL +#endif static unsigned int odev_poll(struct file *file, poll_table * wait) @@ -213,7 +213,8 @@ .open = odev_open, .release = odev_release, .poll = odev_poll, - .ioctl = odev_ioctl, + .unlocked_ioctl = odev_ioctl, + .compat_ioctl = odev_ioctl_compat, }; static snd_minor_t seq_oss_reg = { diff -Nru a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c --- a/sound/core/seq/oss/seq_oss_midi.c 2005-03-03 21:43:46 -08:00 +++ b/sound/core/seq/oss/seq_oss_midi.c 2005-03-03 21:43:46 -08:00 @@ -56,7 +56,7 @@ static int max_midi_devs; static seq_oss_midi_t *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS]; -static spinlock_t register_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(register_lock); /* * prototypes diff -Nru a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c --- a/sound/core/seq/oss/seq_oss_readq.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/oss/seq_oss_readq.c 2005-03-03 21:43:47 -08:00 @@ -24,6 +24,7 @@ #include "seq_oss_event.h" #include #include "../seq_lock.h" +#include /* * constants @@ -165,7 +166,9 @@ void snd_seq_oss_readq_wait(seq_oss_readq_t *q) { - interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout); + wait_event_interruptible_timeout(q->midi_sleep, + (q->qlen > 0 || q->head == q->tail), + q->pre_event_timeout); } /* diff -Nru a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c --- a/sound/core/seq/oss/seq_oss_synth.c 2005-03-03 21:43:46 -08:00 +++ b/sound/core/seq/oss/seq_oss_synth.c 2005-03-03 21:43:46 -08:00 @@ -75,7 +75,7 @@ "MIDI", /* name */ }; -static spinlock_t register_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(register_lock); /* * prototypes diff -Nru a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c --- a/sound/core/seq/oss/seq_oss_writeq.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/oss/seq_oss_writeq.c 2005-03-03 21:43:47 -08:00 @@ -26,6 +26,7 @@ #include #include "../seq_lock.h" #include "../seq_clientmgr.h" +#include /* @@ -91,7 +92,6 @@ { seq_oss_devinfo_t *dp = q->dp; abstime_t time; - unsigned long flags; time = snd_seq_oss_timer_cur_tick(dp->timer); if (q->sync_time >= time) @@ -115,27 +115,13 @@ snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0); } - spin_lock_irqsave(&q->sync_lock, flags); - if (! q->sync_event_put) { /* echoback event has been received */ - spin_unlock_irqrestore(&q->sync_lock, flags); - return 0; - } - - /* wait for echo event */ - spin_unlock(&q->sync_lock); - interruptible_sleep_on_timeout(&q->sync_sleep, HZ); - spin_lock(&q->sync_lock); - if (signal_pending(current)) { + wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ); + if (signal_pending(current)) /* interrupted - return 0 to finish sync */ q->sync_event_put = 0; - spin_unlock_irqrestore(&q->sync_lock, flags); - return 0; - } - spin_unlock_irqrestore(&q->sync_lock, flags); - if (q->sync_time >= time) + if (! q->sync_event_put || q->sync_time >= time) return 0; - else - return 1; + return 1; } /* diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c --- a/sound/core/seq/seq_clientmgr.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/seq_clientmgr.c 2005-03-03 21:43:47 -08:00 @@ -37,8 +37,8 @@ #include "seq_info.h" #include "seq_system.h" #include -#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE) -#include "../ioctl32/ioctl32.h" +#ifdef CONFIG_COMPAT +#include #endif /* Client Manager @@ -51,7 +51,7 @@ #define SNDRV_SEQ_LFLG_OUTPUT 0x0002 #define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) -static spinlock_t clients_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(clients_lock); static DECLARE_MUTEX(register_mutex); /* @@ -413,7 +413,7 @@ } count -= sizeof(snd_seq_event_t); buf += sizeof(snd_seq_event_t); - err = snd_seq_expand_var_event(&cell->event, count, buf, 0, sizeof(snd_seq_event_t)); + err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t)); if (err < 0) break; result += err; @@ -1012,7 +1012,7 @@ event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t); len += extlen; /* increment data length */ } else { -#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE) +#ifdef CONFIG_COMPAT if (client->convert32 && snd_seq_ev_is_varusr(&event)) { void *ptr = compat_ptr(event.data.raw32.d[1]); event.data.ext.ptr = ptr; @@ -2131,21 +2131,20 @@ } -static int snd_seq_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { client_t *client = (client_t *) file->private_data; - int err; snd_assert(client != NULL, return -ENXIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_do_ioctl(client, cmd, (void __user *) arg); - lock_kernel(); - return err; + return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } +#ifdef CONFIG_COMPAT +#include "seq_compat.c" +#else +#define snd_seq_ioctl_compat NULL +#endif /* -------------------------------------------------------- */ @@ -2321,7 +2320,7 @@ if (client == NULL) return -ENXIO; fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, arg); + result = snd_seq_do_ioctl(client, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -2462,7 +2461,8 @@ .open = snd_seq_open, .release = snd_seq_release, .poll = snd_seq_poll, - .ioctl = snd_seq_ioctl, + .unlocked_ioctl = snd_seq_ioctl, + .compat_ioctl = snd_seq_ioctl_compat, }; static snd_minor_t snd_seq_reg = diff -Nru a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/core/seq/seq_compat.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,137 @@ +/* + * 32bit -> 64bit ioctl wrapper for sequencer API + * Copyright (c) by Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from seq.c */ + +#include + +struct sndrv_seq_port_info32 { + struct sndrv_seq_addr addr; /* client/port numbers */ + char name[64]; /* port name */ + + u32 capability; /* port capability bits */ + u32 type; /* port type bits */ + s32 midi_channels; /* channels per MIDI port */ + s32 midi_voices; /* voices per MIDI port */ + s32 synth_voices; /* voices per SYNTH port */ + + s32 read_use; /* R/O: subscribers for output (from this port) */ + s32 write_use; /* R/O: subscribers for input (to this port) */ + + u32 kernel; /* reserved for kernel use (must be NULL) */ + u32 flags; /* misc. conditioning */ + unsigned char time_queue; /* queue # for timestamping */ + char reserved[59]; /* for future use */ +}; + +static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd, + struct sndrv_seq_port_info32 __user *data32) +{ + int err = -EFAULT; + snd_seq_port_info_t *data; + mm_segment_t fs; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + if (copy_from_user(data, data32, sizeof(*data32)) || + get_user(data->flags, &data32->flags) || + get_user(data->time_queue, &data32->time_queue)) + goto error; + data->kernel = NULL; + + fs = snd_enter_user(); + err = snd_seq_do_ioctl(client, cmd, data); + snd_leave_user(fs); + if (err < 0) + goto error; + + if (copy_to_user(data32, data, sizeof(*data32)) || + put_user(data->flags, &data32->flags) || + put_user(data->time_queue, &data32->time_queue)) + err = -EFAULT; + + error: + kfree(data); + return err; +} + + + +/* + */ + +enum { + SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32), +}; + +static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + client_t *client = (client_t *) file->private_data; + void __user *argp = compat_ptr(arg); + + snd_assert(client != NULL, return -ENXIO); + + switch (cmd) { + case SNDRV_SEQ_IOCTL_PVERSION: + case SNDRV_SEQ_IOCTL_CLIENT_ID: + case SNDRV_SEQ_IOCTL_SYSTEM_INFO: + case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO: + case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO: + case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT: + case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT: + case SNDRV_SEQ_IOCTL_CREATE_QUEUE: + case SNDRV_SEQ_IOCTL_DELETE_QUEUE: + case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO: + case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO: + case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE: + case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS: + case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO: + case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO: + case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER: + case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER: + case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT: + case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT: + case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL: + case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL: + case SNDRV_SEQ_IOCTL_REMOVE_EVENTS: + case SNDRV_SEQ_IOCTL_QUERY_SUBS: + case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: + case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: + case SNDRV_SEQ_IOCTL_RUNNING_MODE: + return snd_seq_do_ioctl(client, cmd, argp); + case SNDRV_SEQ_IOCTL_CREATE_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); + case SNDRV_SEQ_IOCTL_DELETE_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp); + case SNDRV_SEQ_IOCTL_GET_PORT_INFO32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); + case SNDRV_SEQ_IOCTL_SET_PORT_INFO32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); + case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); + } + return -ENOIOCTLCMD; +} diff -Nru a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c --- a/sound/core/seq/seq_instr.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/seq_instr.c 2005-03-03 21:43:47 -08:00 @@ -430,7 +430,7 @@ if (ev->data.ext.len < sizeof(snd_seq_instr_header_t)) goto __return; - if (copy_from_user(&put, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) { + if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) { result = -EFAULT; goto __return; } @@ -466,7 +466,7 @@ if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) { result = ops->put(ops->private_data, instr, - ev->data.ext.ptr + sizeof(snd_seq_instr_header_t), + (void __user *)ev->data.ext.ptr + sizeof(snd_seq_instr_header_t), ev->data.ext.len - sizeof(snd_seq_instr_header_t), atomic, put.cmd); @@ -513,7 +513,7 @@ if (ev->data.ext.len < sizeof(snd_seq_instr_header_t)) goto __return; - if (copy_from_user(&ifree, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) { + if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) { result = -EFAULT; goto __return; } diff -Nru a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c --- a/sound/core/seq/seq_memory.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/seq_memory.c 2005-03-03 21:43:47 -08:00 @@ -90,7 +90,7 @@ if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { char buf[32]; - char __user *curptr = event->data.ext.ptr; + char __user *curptr = (char __user *)event->data.ext.ptr; while (len > 0) { int size = sizeof(buf); if (len < size) @@ -134,7 +134,7 @@ return 0; } -static int seq_copy_in_user(char **bufptr, const void *src, int size) +static int seq_copy_in_user(char __user **bufptr, const void *src, int size) { if (copy_to_user(*bufptr, src, size)) return -EFAULT; @@ -158,7 +158,7 @@ if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { if (! in_kernel) return -EINVAL; - if (copy_from_user(buf, event->data.ext.ptr, len)) + if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len)) return -EFAULT; return newlen; } @@ -336,7 +336,7 @@ tmp->event = src->event; src = src->next; } else if (is_usrptr) { - if (copy_from_user(&tmp->event, buf, size)) { + if (copy_from_user(&tmp->event, (char __user *)buf, size)) { err = -EFAULT; goto __error; } diff -Nru a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c --- a/sound/core/seq/seq_midi_event.c 2005-03-03 21:43:46 -08:00 +++ b/sound/core/seq/seq_midi_event.c 2005-03-03 21:43:46 -08:00 @@ -525,3 +525,15 @@ EXPORT_SYMBOL(snd_midi_event_encode); EXPORT_SYMBOL(snd_midi_event_encode_byte); EXPORT_SYMBOL(snd_midi_event_decode); + +static int __init alsa_seq_midi_event_init(void) +{ + return 0; +} + +static void __exit alsa_seq_midi_event_exit(void) +{ +} + +module_init(alsa_seq_midi_event_init) +module_exit(alsa_seq_midi_event_exit) diff -Nru a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c --- a/sound/core/seq/seq_queue.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/seq_queue.c 2005-03-03 21:43:47 -08:00 @@ -49,7 +49,7 @@ /* list of allocated queues */ static queue_t *queue_list[SNDRV_SEQ_MAX_QUEUES]; -static spinlock_t queue_list_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(queue_list_lock); /* number of queues allocated */ static int num_queues; @@ -650,7 +650,7 @@ /* * send events to all subscribed ports */ -static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop) +static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop) { snd_seq_event_t sev; @@ -661,60 +661,58 @@ sev.queue = q->queue; sev.data.queue.queue = q->queue; - if (from_timer_port) { - /* broadcast events from Timer port */ - sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM; - sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; - sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop); - } + /* broadcast events from Timer port */ + sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM; + sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; + sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; + snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop); } /* * process a received queue-control event. * this function is exported for seq_sync.c. */ -void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop) +void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop) { switch (ev->type) { case SNDRV_SEQ_EVENT_START: snd_seq_prioq_leave(q->tickq, ev->source.client, 1); snd_seq_prioq_leave(q->timeq, ev->source.client, 1); if (! snd_seq_timer_start(q->timer)) - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); break; case SNDRV_SEQ_EVENT_CONTINUE: if (! snd_seq_timer_continue(q->timer)) - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); break; case SNDRV_SEQ_EVENT_STOP: snd_seq_timer_stop(q->timer); - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); break; case SNDRV_SEQ_EVENT_TEMPO: snd_seq_timer_set_tempo(q->timer, ev->data.queue.param.value); - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); break; case SNDRV_SEQ_EVENT_SETPOS_TICK: if (snd_seq_timer_set_position_tick(q->timer, ev->data.queue.param.time.tick) == 0) { - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); } break; case SNDRV_SEQ_EVENT_SETPOS_TIME: if (snd_seq_timer_set_position_time(q->timer, ev->data.queue.param.time.time) == 0) { - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); } break; case SNDRV_SEQ_EVENT_QUEUE_SKEW: if (snd_seq_timer_set_skew(q->timer, ev->data.queue.param.skew.value, ev->data.queue.param.skew.base) == 0) { - queue_broadcast_event(q, ev, from_timer_port, atomic, hop); + queue_broadcast_event(q, ev, atomic, hop); } break; } @@ -740,7 +738,7 @@ return -EPERM; } - snd_seq_queue_process_event(q, ev, 1, atomic, hop); + snd_seq_queue_process_event(q, ev, atomic, hop); queue_access_unlock(q); queuefree(q); diff -Nru a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h --- a/sound/core/seq/seq_queue.h 2005-03-03 21:43:47 -08:00 +++ b/sound/core/seq/seq_queue.h 2005-03-03 21:43:47 -08:00 @@ -111,7 +111,7 @@ int snd_seq_queue_is_used(int queueid, int client); int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop); -void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop); +void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop); /* * 64bit division - for sync stuff.. diff -Nru a/sound/core/sound.c b/sound/core/sound.c --- a/sound/core/sound.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/sound.c 2005-03-03 21:43:47 -08:00 @@ -420,7 +420,9 @@ #ifdef CONFIG_PM EXPORT_SYMBOL(snd_power_wait); EXPORT_SYMBOL(snd_card_set_pm_callback); -EXPORT_SYMBOL(snd_card_set_dev_pm_callback); +#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) +EXPORT_SYMBOL(snd_card_set_generic_pm_callback); +#endif #ifdef CONFIG_PCI EXPORT_SYMBOL(snd_card_pci_suspend); EXPORT_SYMBOL(snd_card_pci_resume); @@ -467,6 +469,10 @@ EXPORT_SYMBOL(snd_ctl_notify); EXPORT_SYMBOL(snd_ctl_register_ioctl); EXPORT_SYMBOL(snd_ctl_unregister_ioctl); +#ifdef CONFIG_COMPAT +EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); +EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); +#endif EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); /* misc.c */ diff -Nru a/sound/core/timer.c b/sound/core/timer.c --- a/sound/core/timer.c 2005-03-03 21:43:47 -08:00 +++ b/sound/core/timer.c 2005-03-03 21:43:47 -08:00 @@ -76,7 +76,7 @@ static LIST_HEAD(snd_timer_slave_list); /* lock for slave active lists */ -static spinlock_t slave_active_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(slave_active_lock); static DECLARE_MUTEX(register_mutex); @@ -1653,8 +1653,7 @@ return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; } -static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_timer_user_t *tu; void __user *argp = (void __user *)arg; @@ -1701,17 +1700,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_timer_user_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_timer_user_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_timer_user_fasync(int fd, struct file * file, int on) { snd_timer_user_t *tu; @@ -1803,6 +1791,12 @@ return mask; } +#ifdef CONFIG_COMPAT +#include "timer_compat.c" +#else +#define snd_timer_user_ioctl_compat NULL +#endif + static struct file_operations snd_timer_f_ops = { .owner = THIS_MODULE, @@ -1810,7 +1804,8 @@ .open = snd_timer_user_open, .release = snd_timer_user_release, .poll = snd_timer_user_poll, - .ioctl = snd_timer_user_ioctl, + .unlocked_ioctl = snd_timer_user_ioctl, + .compat_ioctl = snd_timer_user_ioctl_compat, .fasync = snd_timer_user_fasync, }; diff -Nru a/sound/core/timer_compat.c b/sound/core/timer_compat.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/core/timer_compat.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,119 @@ +/* + * 32bit -> 64bit ioctl wrapper for timer API + * Copyright (c) by Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from timer.c */ + +#include + +struct sndrv_timer_info32 { + u32 flags; + s32 card; + unsigned char id[64]; + unsigned char name[80]; + u32 reserved0; + u32 resolution; + unsigned char reserved[64]; +}; + +static int snd_timer_user_info_compat(struct file *file, + struct sndrv_timer_info32 __user *_info) +{ + snd_timer_user_t *tu; + struct sndrv_timer_info32 info; + snd_timer_t *t; + + tu = file->private_data; + snd_assert(tu->timeri != NULL, return -ENXIO); + t = tu->timeri->timer; + snd_assert(t != NULL, return -ENXIO); + memset(&info, 0, sizeof(info)); + info.card = t->card ? t->card->number : -1; + if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) + info.flags |= SNDRV_TIMER_FLG_SLAVE; + strlcpy(info.id, t->id, sizeof(info.id)); + strlcpy(info.name, t->name, sizeof(info.name)); + info.resolution = t->hw.resolution; + if (copy_to_user(_info, &info, sizeof(*_info))) + return -EFAULT; + return 0; +} + +struct sndrv_timer_status32 { + struct compat_timespec tstamp; + u32 resolution; + u32 lost; + u32 overrun; + u32 queue; + unsigned char reserved[64]; +}; + +static int snd_timer_user_status_compat(struct file *file, + struct sndrv_timer_status32 __user *_status) +{ + snd_timer_user_t *tu; + snd_timer_status_t status; + + tu = file->private_data; + snd_assert(tu->timeri != NULL, return -ENXIO); + memset(&status, 0, sizeof(status)); + status.tstamp = tu->tstamp; + status.resolution = snd_timer_resolution(tu->timeri); + status.lost = tu->timeri->lost; + status.overrun = tu->overrun; + spin_lock_irq(&tu->qlock); + status.queue = tu->qused; + spin_unlock_irq(&tu->qlock); + if (copy_to_user(_status, &status, sizeof(status))) + return -EFAULT; + return 0; +} + +/* + */ + +enum { + SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32), + SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32), +}; + +static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *argp = compat_ptr(arg); + + switch (cmd) { + case SNDRV_TIMER_IOCTL_PVERSION: + case SNDRV_TIMER_IOCTL_TREAD: + case SNDRV_TIMER_IOCTL_GINFO: + case SNDRV_TIMER_IOCTL_GPARAMS: + case SNDRV_TIMER_IOCTL_GSTATUS: + case SNDRV_TIMER_IOCTL_SELECT: + case SNDRV_TIMER_IOCTL_PARAMS: + case SNDRV_TIMER_IOCTL_START: + case SNDRV_TIMER_IOCTL_STOP: + case SNDRV_TIMER_IOCTL_CONTINUE: + case SNDRV_TIMER_IOCTL_NEXT_DEVICE: + return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_TIMER_IOCTL_INFO32: + return snd_timer_user_info_compat(file, argp); + case SNDRV_TIMER_IOCTL_STATUS32: + return snd_timer_user_status_compat(file, argp); + } + return -ENOIOCTLCMD; +} diff -Nru a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c --- a/sound/drivers/mpu401/mpu401.c 2005-03-03 21:43:47 -08:00 +++ b/sound/drivers/mpu401/mpu401.c 2005-03-03 21:43:47 -08:00 @@ -1,12 +1,7 @@ /* * Driver for generic MPU-401 boards (UART mode only) * Copyright (c) by Jaroslav Kysela - * - * ACPI PnP Copyright (c) 2004 by Clemens Ladisch - * based on 8250_acpi.c - * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard - * Copyright (C) 2004 Hewlett-Packard Co - * Bjorn Helgaas + * Copyright (c) 2004 by Castet Matthieu * * * This program is free software; you can redistribute it and/or modify @@ -27,27 +22,21 @@ #include #include -#ifdef CONFIG_ACPI_BUS -#include -#endif +#include #include #include #include #include -#ifdef CONFIG_ACPI_BUS -#define USE_ACPI_PNP -#endif - MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("MPU-401 UART"); MODULE_LICENSE("GPL"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -#ifdef USE_ACPI_PNP -static int acpipnp[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; +#ifdef CONFIG_PNP +static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; #endif static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ @@ -58,115 +47,36 @@ MODULE_PARM_DESC(id, "ID string for MPU-401 device."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable MPU-401 device."); -#ifdef USE_ACPI_PNP -module_param_array(acpipnp, bool, NULL, 0444); -MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device."); +#ifdef CONFIG_PNP +module_param_array(pnp, bool, NULL, 0444); +MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device."); #endif module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for MPU-401 device."); module_param_array(irq, int, NULL, 0444); MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); -#ifndef CONFIG_ACPI_BUS -struct acpi_device; -#endif - static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; -static int cards; - -#ifdef USE_ACPI_PNP - -static int acpi_driver_registered; - -struct mpu401_resources { - unsigned long port; - int irq; -}; +static int pnp_registered = 0; -static acpi_status __devinit snd_mpu401_acpi_resource(struct acpi_resource *res, - void *data) -{ - struct mpu401_resources *resources = (struct mpu401_resources *)data; - - if (res->id == ACPI_RSTYPE_IRQ) { - if (res->data.irq.number_of_interrupts > 0) { - resources->irq = acpi_register_gsi(res->data.irq.interrupts[0], - res->data.irq.edge_level, - res->data.irq.active_high_low); - } - } else if (res->id == ACPI_RSTYPE_IO) { - if (res->data.io.range_length >= 2) { - resources->port = res->data.io.min_base_address; - } - } - return AE_OK; -} - -static int __devinit snd_mpu401_acpi_pnp(int dev, struct acpi_device *device) -{ - struct mpu401_resources res; - acpi_status status; - - res.port = SNDRV_AUTO_PORT; - res.irq = SNDRV_AUTO_IRQ; - status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - snd_mpu401_acpi_resource, &res); - if (ACPI_FAILURE(status)) - return -ENODEV; - if (res.port == SNDRV_AUTO_PORT || res.irq == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "no port or irq in %s _CRS\n", - acpi_device_bid(device)); - return -ENODEV; - } - port[dev] = res.port; - irq[dev] = res.irq; - return 0; -} - -#endif /* USE_ACPI_PNP */ - -static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device) +static int snd_mpu401_create(int dev, snd_card_t **rcard) { snd_card_t *card; int err; -#ifdef USE_ACPI_PNP - if (!device) { -#endif - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); - return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "specify or disable IRQ port\n"); - return -EINVAL; - } -#ifdef USE_ACPI_PNP - } -#endif - -#ifdef USE_ACPI_PNP - if (device && (err = snd_mpu401_acpi_pnp(dev, device)) < 0) - return err; -#endif - + *rcard = NULL; card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; strcpy(card->driver, "MPU-401 UART"); strcpy(card->shortname, card->driver); - sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]); + sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); if (irq[dev] >= 0) { - sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]); + sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]); } else { strcat(card->longname, "polled"); } -#ifdef USE_ACPI_PNP - if (device) { - strcat(card->longname, ", ACPI id "); - strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname)); - } -#endif + if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, @@ -179,89 +89,127 @@ snd_card_free(card); return err; } -#ifdef USE_ACPI_PNP - if (device) - acpi_driver_data(device) = card; - else -#endif - snd_mpu401_legacy_cards[dev] = card; - ++cards; + *rcard = card; return 0; } -#ifdef USE_ACPI_PNP +static int __devinit snd_mpu401_probe(int dev) +{ + if (port[dev] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR "specify port\n"); + return -EINVAL; + } + if (irq[dev] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "specify or disable IRQ\n"); + return -EINVAL; + } + return snd_mpu401_create(dev, &snd_mpu401_legacy_cards[dev]); +} + +#ifdef CONFIG_PNP + +#define IO_EXTENT 2 + +static struct pnp_device_id snd_mpu401_pnpids[] = { + { .id = "PNPb006" }, + { .id = "" } +}; + +MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); + +static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device, + const struct pnp_device_id *id) +{ + if (!pnp_port_valid(device, 0) || + pnp_port_flags(device, 0) & IORESOURCE_DISABLED) { + snd_printk(KERN_ERR "no PnP port\n"); + return -ENODEV; + } + if (pnp_port_len(device, 0) < IO_EXTENT) { + snd_printk(KERN_ERR "PnP port length is %ld, expected %d\n", + pnp_port_len(device, 0), IO_EXTENT); + return -ENODEV; + } + port[dev] = pnp_port_start(device, 0); + + if (!pnp_irq_valid(device, 0) || + pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) { + snd_printk(KERN_WARNING "no PnP irq, using polling\n"); + irq[dev] = -1; + } else { + irq[dev] = pnp_irq(device, 0); + } + return 0; +} -static int __devinit snd_mpu401_acpi_add(struct acpi_device *device) +static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *id) { static int dev; + snd_card_t *card; int err; for ( ; dev < SNDRV_CARDS; ++dev) { - if (!enable[dev] || !acpipnp[dev]) + if (!enable[dev] || !pnp[dev]) continue; - err = snd_card_mpu401_probe(dev, device); + err = snd_mpu401_pnp(dev, pnp_dev, id); + if (err < 0) + return err; + err = snd_mpu401_create(dev, &card); if (err < 0) return err; + snd_card_set_dev(card, &pnp_dev->dev); + pnp_set_drvdata(pnp_dev, card); ++dev; return 0; } return -ENODEV; } -static int __devexit snd_mpu401_acpi_remove(struct acpi_device *device, - int type) +static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev) { - snd_card_t *card; - - if (!device) - return -EINVAL; - card = (snd_card_t *)acpi_driver_data(device); - if (!card) - return -EINVAL; + snd_card_t *card = (snd_card_t *) pnp_get_drvdata(dev); snd_card_disconnect(card); snd_card_free_in_thread(card); - acpi_driver_data(device) = NULL; - return 0; } -static struct acpi_driver snd_mpu401_acpi_driver = { - .name = "MPU-401 Driver", - .class = "mpu401", - .ids = "PNPB006", - .ops = { - .add = snd_mpu401_acpi_add, - .remove = __devexit_p(snd_mpu401_acpi_remove), - }, +static struct pnp_driver snd_mpu401_pnp_driver = { + .name = "mpu401", + .id_table = snd_mpu401_pnpids, + .probe = snd_mpu401_pnp_probe, + .remove = __devexit_p(snd_mpu401_pnp_remove), }; - -#endif /* USE_ACPI_PNP */ +#else +static struct pnp_driver snd_mpu401_pnp_driver; +#endif static int __init alsa_card_mpu401_init(void) { - int dev; + int dev, devices = 0; + int err; -#ifdef USE_ACPI_PNP - if (acpi_bus_register_driver(&snd_mpu401_acpi_driver) >= 0) - acpi_driver_registered = 1; -#endif for (dev = 0; dev < SNDRV_CARDS; dev++) { if (!enable[dev]) continue; -#ifdef USE_ACPI_PNP - if (acpipnp[dev] && acpi_driver_registered) +#ifdef CONFIG_PNP + if (pnp[dev]) continue; #endif - snd_card_mpu401_probe(dev, NULL); + if (snd_mpu401_probe(dev) >= 0) + devices++; } - if (!cards) { + if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) { + pnp_registered = 1; + devices += err; + } + + if (!devices) { #ifdef MODULE printk(KERN_ERR "MPU-401 device not found or device busy\n"); #endif -#ifdef USE_ACPI_PNP - if (acpi_driver_registered) - acpi_bus_unregister_driver(&snd_mpu401_acpi_driver); -#endif + if (pnp_registered) + pnp_unregister_driver(&snd_mpu401_pnp_driver); return -ENODEV; } return 0; @@ -271,10 +219,8 @@ { int idx; -#ifdef USE_ACPI_PNP - if (acpi_driver_registered) - acpi_bus_unregister_driver(&snd_mpu401_acpi_driver); -#endif + if (pnp_registered) + pnp_unregister_driver(&snd_mpu401_pnp_driver); for (idx = 0; idx < SNDRV_CARDS; idx++) snd_card_free(snd_mpu401_legacy_cards[idx]); } diff -Nru a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c --- a/sound/drivers/serial-u16550.c 2005-03-03 21:43:47 -08:00 +++ b/sound/drivers/serial-u16550.c 2005-03-03 21:43:47 -08:00 @@ -232,7 +232,7 @@ } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { snd_rawmidi_receive(uart->midi_input[substream], &c, 1); - } + } } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { snd_rawmidi_receive(uart->midi_input[substream], &c, 1); } @@ -840,6 +840,16 @@ return 0; } +static void __init snd_uart16550_substreams(snd_rawmidi_str_t *stream) +{ + struct list_head *list; + + list_for_each(list, &stream->substreams) { + snd_rawmidi_substream_t *substream = list_entry(list, snd_rawmidi_substream_t, list); + sprintf(substream->name, "Serial MIDI %d", substream->number + 1); + } +} + static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, snd_rawmidi_t **rmidi) { snd_rawmidi_t *rrawmidi; @@ -849,7 +859,9 @@ return err; snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input); snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output); - sprintf(rrawmidi->name, "uart16550 MIDI #%d", device); + strcpy(rrawmidi->name, "Serial MIDI"); + snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); + snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; @@ -906,7 +918,7 @@ return -ENOMEM; strcpy(card->driver, "Serial"); - strcpy(card->shortname, "Serial midi (uart16550A)"); + strcpy(card->shortname, "Serial MIDI (UART16550A)"); if ((err = snd_uart16550_create(card, port[dev], diff -Nru a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c --- a/sound/drivers/vx/vx_core.c 2005-03-03 21:43:47 -08:00 +++ b/sound/drivers/vx/vx_core.c 2005-03-03 21:43:47 -08:00 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -45,12 +46,10 @@ */ void snd_vx_delay(vx_core_t *chip, int xmsec) { - if (! in_interrupt() && xmsec >= 1000 / HZ) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((xmsec * HZ + 999) / 1000); - } else { + if (! in_interrupt() && xmsec >= 1000 / HZ) + msleep(xmsec); + else mdelay(xmsec); - } } /* @@ -610,6 +609,10 @@ static char *uer_type[] = { "Consumer", "Professional", "Not Present" }; snd_iprintf(buffer, "%s\n", chip->card->longname); + snd_iprintf(buffer, "Xilinx Firmware: %s\n", + chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No"); + snd_iprintf(buffer, "Device Initialized: %s\n", + chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No"); snd_iprintf(buffer, "DSP audio info:"); if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME) snd_iprintf(buffer, " realtime"); @@ -718,7 +721,7 @@ /* * suspend */ -static int snd_vx_suspend(snd_card_t *card, unsigned int state) +static int snd_vx_suspend(snd_card_t *card, pm_message_t state) { vx_core_t *chip = card->pm_private_data; unsigned int i; @@ -735,7 +738,7 @@ /* * resume */ -static int snd_vx_resume(snd_card_t *card, unsigned int state) +static int snd_vx_resume(snd_card_t *card) { vx_core_t *chip = card->pm_private_data; int i, err; diff -Nru a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c --- a/sound/drivers/vx/vx_hwdep.c 2005-03-03 21:43:47 -08:00 +++ b/sound/drivers/vx/vx_hwdep.c 2005-03-03 21:43:47 -08:00 @@ -21,6 +21,7 @@ */ #include +#include #include #include #include diff -Nru a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile --- a/sound/i2c/other/Makefile 2005-03-03 21:43:47 -08:00 +++ b/sound/i2c/other/Makefile 2005-03-03 21:43:47 -08:00 @@ -3,6 +3,7 @@ # Copyright (c) 2003 by Jaroslav Kysela # +snd-ak4114-objs := ak4114.o snd-ak4117-objs := ak4117.o snd-ak4xxx-adda-objs := ak4xxx-adda.o snd-tea575x-tuner-objs := tea575x-tuner.o @@ -11,4 +12,5 @@ obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o +obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o diff -Nru a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/i2c/other/ak4114.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,580 @@ +/* + * Routines for control of the AK4114 via I2C and 4-wire serial interface + * IEC958 (S/PDIF) receiver by Asahi Kasei + * Copyright (c) by Jaroslav Kysela + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Jaroslav Kysela "); +MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei"); +MODULE_LICENSE("GPL"); + +#define AK4114_ADDR 0x00 /* fixed address */ + +static void ak4114_stats(void *); + +static void reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char val) +{ + ak4114->write(ak4114->private_data, reg, val); + if (reg <= AK4114_REG_INT1_MASK) + ak4114->regmap[reg] = val; + else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4) + ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val; +} + +static inline unsigned char reg_read(ak4114_t *ak4114, unsigned char reg) +{ + return ak4114->read(ak4114->private_data, reg); +} + +#if 0 +static void reg_dump(ak4114_t *ak4114) +{ + int i; + + printk("AK4114 REG DUMP:\n"); + for (i = 0; i < 0x20; i++) + printk("reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0); +} +#endif + +static void snd_ak4114_free(ak4114_t *chip) +{ + chip->init = 1; /* don't schedule new work */ + mb(); + if (chip->workqueue != NULL) { + flush_workqueue(chip->workqueue); + destroy_workqueue(chip->workqueue); + } + kfree(chip); +} + +static int snd_ak4114_dev_free(snd_device_t *device) +{ + ak4114_t *chip = device->device_data; + snd_ak4114_free(chip); + return 0; +} + +int snd_ak4114_create(snd_card_t *card, + ak4114_read_t *read, ak4114_write_t *write, + unsigned char pgm[7], unsigned char txcsb[5], + void *private_data, ak4114_t **r_ak4114) +{ + ak4114_t *chip; + int err = 0; + unsigned char reg; + static snd_device_ops_t ops = { + .dev_free = snd_ak4114_dev_free, + }; + + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + spin_lock_init(&chip->lock); + chip->card = card; + chip->read = read; + chip->write = write; + chip->private_data = private_data; + + for (reg = 0; reg < 7; reg++) + chip->regmap[reg] = pgm[reg]; + for (reg = 0; reg < 5; reg++) + chip->txcsb[reg] = txcsb[reg]; + + chip->workqueue = create_workqueue("snd-ak4114"); + if (chip->workqueue == NULL) { + kfree(chip); + return -ENOMEM; + } + + snd_ak4114_reinit(chip); + + chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); + chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); + + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) + goto __fail; + + if (r_ak4114) + *r_ak4114 = chip; + return 0; + + __fail: + snd_ak4114_free(chip); + return err < 0 ? err : -EIO; +} + +void snd_ak4114_reg_write(ak4114_t *chip, unsigned char reg, unsigned char mask, unsigned char val) +{ + if (reg <= AK4114_REG_INT1_MASK) + reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); + else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) + reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val); +} + +void snd_ak4114_reinit(ak4114_t *chip) +{ + unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg; + + chip->init = 1; + mb(); + flush_workqueue(chip->workqueue); + /* bring the chip to reset state and powerdown state */ + reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); + udelay(200); + /* release reset, but leave powerdown */ + reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN); + udelay(200); + for (reg = 1; reg < 7; reg++) + reg_write(chip, reg, chip->regmap[reg]); + for (reg = 0; reg < 5; reg++) + reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]); + /* release powerdown, everything is initialized now */ + reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); + /* bring up statistics / event queing */ + chip->init = 0; + INIT_WORK(&chip->work, ak4114_stats, chip); + queue_delayed_work(chip->workqueue, &chip->work, 1); +} + +static unsigned int external_rate(unsigned char rcs1) +{ + switch (rcs1 & (AK4114_FS0|AK4114_FS1|AK4114_FS2|AK4114_FS3)) { + case AK4114_FS_32000HZ: return 32000; + case AK4114_FS_44100HZ: return 44100; + case AK4114_FS_48000HZ: return 48000; + case AK4114_FS_88200HZ: return 88200; + case AK4114_FS_96000HZ: return 96000; + case AK4114_FS_176400HZ: return 176400; + case AK4114_FS_192000HZ: return 192000; + default: return 0; + } +} + +static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = LONG_MAX; + return 0; +} + +static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + long *ptr; + + spin_lock_irq(&chip->lock); + ptr = (long *)(((char *)chip) + kcontrol->private_value); + ucontrol->value.integer.value[0] = *ptr; + *ptr = 0; + spin_unlock_irq(&chip->lock); + return 0; +} + +static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + unsigned char reg = kcontrol->private_value & 0xff; + unsigned char bit = (kcontrol->private_value >> 8) & 0xff; + unsigned char inv = (kcontrol->private_value >> 31) & 1; + + ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; + return 0; +} + +static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 192000; + return 0; +} + +static int snd_ak4114_rate_get(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4114_REG_RCS1)); + return 0; +} + +static int snd_ak4114_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +static int snd_ak4114_spdif_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + unsigned i; + + for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++) + ucontrol->value.iec958.status[i] = reg_read(chip, AK4114_REG_RXCSB0 + i); + return 0; +} + +static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + unsigned i; + + for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++) + ucontrol->value.iec958.status[i] = chip->txcsb[i]; + return 0; +} + +static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + unsigned i; + + for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++) + reg_write(chip, AK4114_REG_TXCSB0 + i, ucontrol->value.iec958.status[i]); + return 0; +} + +static int snd_ak4114_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +static int snd_ak4114_spdif_mask_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + memset(ucontrol->value.iec958.status, 0xff, AK4114_REG_RXCSB_SIZE); + return 0; +} + +static int snd_ak4114_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xffff; + uinfo->count = 4; + return 0; +} + +static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + unsigned short tmp; + + ucontrol->value.integer.value[0] = 0xf8f2; + ucontrol->value.integer.value[1] = 0x4e1f; + tmp = reg_read(chip, AK4114_REG_Pc0) | (reg_read(chip, AK4114_REG_Pc1) << 8); + ucontrol->value.integer.value[2] = tmp; + tmp = reg_read(chip, AK4114_REG_Pd0) | (reg_read(chip, AK4114_REG_Pd1) << 8); + ucontrol->value.integer.value[3] = tmp; + return 0; +} + +static int snd_ak4114_spdif_qinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = AK4114_REG_QSUB_SIZE; + return 0; +} + +static int snd_ak4114_spdif_qget(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + ak4114_t *chip = snd_kcontrol_chip(kcontrol); + unsigned i; + + for (i = 0; i < AK4114_REG_QSUB_SIZE; i++) + ucontrol->value.bytes.data[i] = reg_read(chip, AK4114_REG_QSUB_ADDR + i); + return 0; +} + +/* Don't forget to change AK4114_CONTROLS define!!! */ +static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = { +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 Parity Errors", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_error_info, + .get = snd_ak4114_in_error_get, + .private_value = offsetof(ak4114_t, parity_errors), +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 V-Bit Errors", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_error_info, + .get = snd_ak4114_in_error_get, + .private_value = offsetof(ak4114_t, v_bit_errors), +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 C-CRC Errors", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_error_info, + .get = snd_ak4114_in_error_get, + .private_value = offsetof(ak4114_t, ccrc_errors), +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 Q-CRC Errors", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_error_info, + .get = snd_ak4114_in_error_get, + .private_value = offsetof(ak4114_t, qcrc_errors), +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 External Rate", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_rate_info, + .get = snd_ak4114_rate_get, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .info = snd_ak4114_spdif_mask_info, + .get = snd_ak4114_spdif_mask_get, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_spdif_info, + .get = snd_ak4114_spdif_playback_get, + .put = snd_ak4114_spdif_playback_put, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .info = snd_ak4114_spdif_mask_info, + .get = snd_ak4114_spdif_mask_get, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_spdif_info, + .get = snd_ak4114_spdif_get, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 Preample Capture Default", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_spdif_pinfo, + .get = snd_ak4114_spdif_pget, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 Q-subcode Capture Default", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_spdif_qinfo, + .get = snd_ak4114_spdif_qget, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 Audio", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_bit_info, + .get = snd_ak4114_in_bit_get, + .private_value = (1<<31) | (1<<8) | AK4114_REG_RCS0, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 Non-PCM Bitstream", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_bit_info, + .get = snd_ak4114_in_bit_get, + .private_value = (6<<8) | AK4114_REG_RCS1, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 DTS Bitstream", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_bit_info, + .get = snd_ak4114_in_bit_get, + .private_value = (3<<8) | AK4114_REG_RCS1, +} +}; + +int snd_ak4114_build(ak4114_t *ak4114, + snd_pcm_substream_t *ply_substream, + snd_pcm_substream_t *cap_substream) +{ + snd_kcontrol_t *kctl; + unsigned int idx; + int err; + + snd_assert(cap_substream, return -EINVAL); + ak4114->playback_substream = ply_substream; + ak4114->capture_substream = cap_substream; + for (idx = 0; idx < AK4114_CONTROLS; idx++) { + kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114); + if (kctl == NULL) + return -ENOMEM; + if (!strstr(kctl->id.name, "Playback")) { + if (ply_substream == NULL) { + snd_ctl_free_one(kctl); + ak4114->kctls[idx] = NULL; + continue; + } + kctl->id.device = ply_substream->pcm->device; + kctl->id.subdevice = ply_substream->number; + } else { + kctl->id.device = cap_substream->pcm->device; + kctl->id.subdevice = cap_substream->number; + } + err = snd_ctl_add(ak4114->card, kctl); + if (err < 0) + return err; + ak4114->kctls[idx] = kctl; + } + return 0; +} + +int snd_ak4114_external_rate(ak4114_t *ak4114) +{ + unsigned char rcs1; + + rcs1 = reg_read(ak4114, AK4114_REG_RCS1); + return external_rate(rcs1); +} + +int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags) +{ + snd_pcm_runtime_t *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL; + unsigned long _flags; + int res = 0; + unsigned char rcs0, rcs1; + unsigned char c0, c1; + + rcs1 = reg_read(ak4114, AK4114_REG_RCS1); + if (flags & AK4114_CHECK_NO_STAT) + goto __rate; + rcs0 = reg_read(ak4114, AK4114_REG_RCS0); + spin_lock_irqsave(&ak4114->lock, _flags); + if (rcs0 & AK4114_PAR) + ak4114->parity_errors++; + if (rcs1 & AK4114_V) + ak4114->v_bit_errors++; + if (rcs1 & AK4114_CCRC) + ak4114->ccrc_errors++; + if (rcs1 & AK4114_QCRC) + ak4114->qcrc_errors++; + c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ + (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); + c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); + ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT); + ak4114->rcs1 = rcs1; + spin_unlock_irqrestore(&ak4114->lock, _flags); + + if (rcs0 & AK4114_PAR) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[0]->id); + if (rcs0 & AK4114_V) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[1]->id); + if (rcs1 & AK4114_CCRC) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[2]->id); + if (rcs1 & AK4114_QCRC) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[3]->id); + + /* rate change */ + if (c1 & 0xf0) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[4]->id); + + if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT)) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[9]->id); + if (c0 & AK4114_QINT) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[10]->id); + + if (c0 & AK4114_AUDION) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[11]->id); + if (c0 & AK4114_AUTO) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[12]->id); + if (c0 & AK4114_DTSCD) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[13]->id); + + if (ak4114->change_callback && (c0 | c1) != 0) + ak4114->change_callback(ak4114, c0, c1); + + __rate: + /* compare rate */ + res = external_rate(rcs1); + if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) { + snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags); + if (snd_pcm_running(ak4114->capture_substream)) { + // printk("rate changed (%i <- %i)\n", runtime->rate, res); + snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); + wake_up(&runtime->sleep); + res = 1; + } + snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); + } + return res; +} + +static void ak4114_stats(void *data) +{ + ak4114_t *chip = (ak4114_t *)data; + + if (chip->init) + return; + snd_ak4114_check_rate_and_errors(chip, 0); + queue_delayed_work(chip->workqueue, &chip->work, 1); +} + +EXPORT_SYMBOL(snd_ak4114_create); +EXPORT_SYMBOL(snd_ak4114_reg_write); +EXPORT_SYMBOL(snd_ak4114_reinit); +EXPORT_SYMBOL(snd_ak4114_build); +EXPORT_SYMBOL(snd_ak4114_external_rate); +EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); diff -Nru a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c --- a/sound/i2c/other/ak4xxx-adda.c 2005-03-03 21:43:47 -08:00 +++ b/sound/i2c/other/ak4xxx-adda.c 2005-03-03 21:43:47 -08:00 @@ -1,8 +1,8 @@ /* - * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4381 + * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381 * AD and DA converters * - * Copyright (c) 2000-2003 Jaroslav Kysela , + * Copyright (c) 2000-2004 Jaroslav Kysela , * Takashi Iwai * * This program is free software; you can redistribute it and/or modify @@ -84,6 +84,7 @@ /* FIXME: needed for ak4529? */ break; case SND_AK4355: + case SND_AK4358: if (state) { snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ return; @@ -166,6 +167,24 @@ 0x01, 0x01, /* 1: un-reset, unmute */ 0xff, 0xff }; + static unsigned char inits_ak4358[] = { + 0x01, 0x02, /* 1: reset and soft-mute */ + 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ + 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ + // 0x02, 0x2e, /* quad speed */ + 0x03, 0x01, /* 3: de-emphasis off */ + 0x04, 0x00, /* 4: LOUT1 volume muted */ + 0x05, 0x00, /* 5: ROUT1 volume muted */ + 0x06, 0x00, /* 6: LOUT2 volume muted */ + 0x07, 0x00, /* 7: ROUT2 volume muted */ + 0x08, 0x00, /* 8: LOUT3 volume muted */ + 0x09, 0x00, /* 9: ROUT3 volume muted */ + 0x0b, 0x00, /* b: LOUT4 volume muted */ + 0x0c, 0x00, /* c: ROUT4 volume muted */ + 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ + 0x01, 0x01, /* 1: un-reset, unmute */ + 0xff, 0xff + }; static unsigned char inits_ak4381[] = { 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ 0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */ @@ -197,6 +216,10 @@ inits = inits_ak4355; num_chips = 1; break; + case SND_AK4358: + inits = inits_ak4358; + num_chips = 1; + break; case SND_AK4381: inits = inits_ak4381; num_chips = ak->num_dacs / 2; @@ -370,6 +393,12 @@ case SND_AK4355: ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */ break; + case SND_AK4358: + if (idx >= 6) + ctl.private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */ + else + ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */ + break; case SND_AK4381: ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */ break; @@ -407,7 +436,7 @@ if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) return err; } - if (ak->type == SND_AK4355) + if (ak->type == SND_AK4355 || ak->type == SND_AK4358) num_emphs = 1; else num_emphs = ak->num_dacs / 2; @@ -432,6 +461,7 @@ break; } case SND_AK4355: + case SND_AK4358: ctl.private_value = AK_COMPOSE(idx, 3, 0, 0); break; case SND_AK4381: diff -Nru a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c --- a/sound/i2c/other/tea575x-tuner.c 2005-03-03 21:43:47 -08:00 +++ b/sound/i2c/other/tea575x-tuner.c 2005-03-03 21:43:47 -08:00 @@ -168,6 +168,10 @@ } } +static void snd_tea575x_release(struct video_device *vfd) +{ +} + /* * initialize all the tea575x chips */ @@ -186,6 +190,7 @@ strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio"); tea->vd.type = VID_TYPE_TUNER; tea->vd.hardware = VID_HARDWARE_RTRACK; /* FIXME: assign new number */ + tea->vd.release = snd_tea575x_release; video_set_drvdata(&tea->vd, tea); tea->vd.fops = &tea->fops; tea->fops.owner = tea->card->module; diff -Nru a/sound/isa/Kconfig b/sound/isa/Kconfig --- a/sound/isa/Kconfig 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/Kconfig 2005-03-03 21:43:47 -08:00 @@ -20,6 +20,7 @@ tristate "Generic AD1848/CS4248 driver" depends on SND select SND_PCM + select SND_GENERIC_PM help Say Y here to include support for AD1848 (Analog Devices) or CS4248 (Cirrus Logic - Crystal Semiconductors) chips. @@ -35,6 +36,7 @@ depends on SND select SND_MPU401_UART select SND_PCM + select SND_GENERIC_PM help Say Y here to include support for CS4231 chips from Cirrus Logic - Crystal Semiconductors. @@ -48,6 +50,7 @@ select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM + select SND_GENERIC_PM help Say Y here to include support for CS4232 chips from Cirrus Logic - Crystal Semiconductors. @@ -61,6 +64,7 @@ select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM + select SND_GENERIC_PM help Say Y to include support for CS4235,CS4236,CS4237B,CS4238B, CS4239 chips from Cirrus Logic - Crystal Semiconductors. @@ -98,6 +102,7 @@ select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM + select SND_GENERIC_PM help Say Y here to include support for ESS AudioDrive ES18xx chips. @@ -332,6 +337,7 @@ select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM + select SND_GENERIC_PM help Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3 chips. diff -Nru a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c --- a/sound/isa/ad1848/ad1848_lib.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/ad1848/ad1848_lib.c 2005-03-03 21:43:47 -08:00 @@ -644,7 +644,7 @@ } #ifdef CONFIG_PM -static int snd_ad1848_suspend(snd_card_t *card, unsigned int state) +static int snd_ad1848_suspend(snd_card_t *card, pm_message_t state) { ad1848_t *chip = card->pm_private_data; @@ -657,7 +657,7 @@ return 0; } -static int snd_ad1848_resume(snd_card_t *card, unsigned int state) +static int snd_ad1848_resume(snd_card_t *card) { ad1848_t *chip = card->pm_private_data; diff -Nru a/sound/isa/als100.c b/sound/isa/als100.c --- a/sound/isa/als100.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/als100.c 2005-03-03 21:43:47 -08:00 @@ -121,7 +121,7 @@ return -ENODEV; } acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev); - acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu); + acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev); pdev = acard->dev; diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c --- a/sound/isa/cs423x/cs4231_lib.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/cs423x/cs4231_lib.c 2005-03-03 21:43:47 -08:00 @@ -1394,7 +1394,7 @@ #endif } -static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state) +static int snd_cs4231_pm_suspend(snd_card_t *card, pm_message_t state) { cs4231_t *chip = card->pm_private_data; if (chip->suspend) @@ -1402,7 +1402,7 @@ return 0; } -static int snd_cs4231_pm_resume(snd_card_t *card, unsigned int state) +static int snd_cs4231_pm_resume(snd_card_t *card) { cs4231_t *chip = card->pm_private_data; if (chip->resume) diff -Nru a/sound/isa/es18xx.c b/sound/isa/es18xx.c --- a/sound/isa/es18xx.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/es18xx.c 2005-03-03 21:43:47 -08:00 @@ -1612,7 +1612,7 @@ /* Power Management support functions */ #ifdef CONFIG_PM -static int snd_es18xx_suspend(snd_card_t *card, unsigned int state) +static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state) { es18xx_t *chip = card->pm_private_data; @@ -1627,7 +1627,7 @@ return 0; } -static int snd_es18xx_resume(snd_card_t *card, unsigned int state) +static int snd_es18xx_resume(snd_card_t *card) { es18xx_t *chip = card->pm_private_data; diff -Nru a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c --- a/sound/isa/gus/gus_pcm.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/gus/gus_pcm.c 2005-03-03 21:43:47 -08:00 @@ -333,6 +333,7 @@ } } if (count > 0 && !in_interrupt()) { + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); if (signal_pending(current)) return -EAGAIN; @@ -696,16 +697,10 @@ snd_gus_card_t *gus = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; gus_pcm_private_t *pcmp = runtime->private_data; - unsigned long jiffies_old; + + if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ)) + snd_printk("gf1 pcm - serious DMA problem\n"); - jiffies_old = jiffies; - while (atomic_read(&pcmp->dma_count) > 0) { - interruptible_sleep_on_timeout(&pcmp->sleep, 1); - if ((signed long)(jiffies - jiffies_old) > 2*HZ) { - snd_printk("gf1 pcm - serious DMA problem\n"); - break; - } - } snd_gf1_dma_done(gus); return 0; } diff -Nru a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c --- a/sound/isa/gus/gus_reset.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/gus/gus_reset.c 2005-03-03 21:43:47 -08:00 @@ -207,7 +207,6 @@ unsigned long flags; short i, ramp_ok; unsigned short ramp_end; - long time; if (!in_interrupt()) { /* this can't be done in interrupt */ for (i = v_min, ramp_ok = 0; i <= v_max; i++) { @@ -227,11 +226,7 @@ } spin_unlock_irqrestore(&gus->reg_lock, flags); } - time = HZ / 20; - while (time > 0 && !signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); - } + msleep_interruptible(50); } snd_gf1_clear_voices(gus, v_min, v_max); } diff -Nru a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c --- a/sound/isa/gus/interwave.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/gus/interwave.c 2005-03-03 21:43:47 -08:00 @@ -79,8 +79,10 @@ MODULE_PARM_DESC(id, "ID string for InterWave soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable InterWave soundcard."); +#ifdef CONFIG_PNP module_param_array(isapnp, bool, NULL, 0444); MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); +#endif module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for InterWave driver."); #ifdef SNDRV_STB diff -Nru a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c --- a/sound/isa/opl3sa2.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/opl3sa2.c 2005-03-03 21:43:47 -08:00 @@ -529,7 +529,7 @@ /* Power Management support functions */ #ifdef CONFIG_PM -static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state) +static int snd_opl3sa2_suspend(snd_card_t *card, pm_message_t state) { opl3sa2_t *chip = card->pm_private_data; @@ -542,7 +542,7 @@ return 0; } -static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state) +static int snd_opl3sa2_resume(snd_card_t *card) { opl3sa2_t *chip = card->pm_private_data; int i; @@ -787,7 +787,7 @@ int res; for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] && !isapnp[dev]) + if (!enable[dev] || !isapnp[dev]) continue; res = snd_opl3sa2_probe(dev, card, id); if (res < 0) diff -Nru a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c --- a/sound/isa/sb/emu8000.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/sb/emu8000.c 2005-03-03 21:43:47 -08:00 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -355,8 +356,7 @@ { send_array(emu, init1, ARRAY_SIZE(init1)/4); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */ + msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */ send_array(emu, init2, ARRAY_SIZE(init2)/4); send_array(emu, init3, ARRAY_SIZE(init3)/4); diff -Nru a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c --- a/sound/isa/wavefront/wavefront_synth.c 2005-03-03 21:43:47 -08:00 +++ b/sound/isa/wavefront/wavefront_synth.c 2005-03-03 21:43:47 -08:00 @@ -1751,6 +1751,7 @@ outb (val,port); spin_unlock_irq(&dev->irq_lock); while (1) { + set_current_state(TASK_INTERRUPTIBLE); if ((timeout = schedule_timeout(timeout)) == 0) return; if (dev->irq_ok) @@ -1942,7 +1943,7 @@ fs = get_fs(); set_fs (get_ds()); - if ((fd = sys_open (path, 0, 0)) < 0) { + if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) { snd_printk ("Unable to load \"%s\".\n", path); return 1; @@ -1951,7 +1952,7 @@ while (1) { int x; - if ((x = sys_read (fd, §ion_length, sizeof (section_length))) != + if ((x = sys_read (fd, (char __user *) §ion_length, sizeof (section_length))) != sizeof (section_length)) { snd_printk ("firmware read error.\n"); goto failure; @@ -1967,7 +1968,7 @@ goto failure; } - if (sys_read (fd, section, section_length) != section_length) { + if (sys_read (fd, (char __user *) section, section_length) != section_length) { snd_printk ("firmware section " "read error.\n"); goto failure; diff -Nru a/sound/pci/Kconfig b/sound/pci/Kconfig --- a/sound/pci/Kconfig 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/Kconfig 2005-03-03 21:43:47 -08:00 @@ -514,5 +514,15 @@ To compile this driver as a module, choose M here: the module will be called snd-vx222. -endmenu +config SND_HDA_INTEL + tristate "Intel HD Audio" + depends on SND + select SND_PCM + help + Say Y here to include support for Intel "High Definition + Audio" (Azalia) motherboard devices. + + To compile this driver as a module, choose M here: the module + will be called snd-hda-intel. +endmenu diff -Nru a/sound/pci/Makefile b/sound/pci/Makefile --- a/sound/pci/Makefile 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/Makefile 2005-03-03 21:43:46 -08:00 @@ -53,6 +53,7 @@ ca0106/ \ cs46xx/ \ emu10k1/ \ + hda/ \ ice1712/ \ korg1212/ \ mixart/ \ diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c --- a/sound/pci/ac97/ac97_codec.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ac97/ac97_codec.c 2005-03-03 21:43:47 -08:00 @@ -438,9 +438,10 @@ } /* - * + * Controls */ +/* input mux */ static int snd_ac97_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { static char *texts[8] = { @@ -481,6 +482,7 @@ return snd_ac97_update(ac97, AC97_REC_SEL, val); } +/* standard stereo enums */ #define AC97_ENUM_DOUBLE(xname, reg, shift, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \ .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \ @@ -543,6 +545,30 @@ return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift); } +/* save/restore ac97 v2.3 paging */ +static int snd_ac97_page_save(ac97_t *ac97, int reg, snd_kcontrol_t *kcontrol) +{ + int page_save = -1; + if ((kcontrol->private_value & (1<<25)) && + (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && + (reg >= 0x60 && reg < 0x70)) { + unsigned short page = (kcontrol->private_value >> 26) & 0x0f; + down(&ac97->page_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); + } + return page_save; +} + +static void snd_ac97_page_restore(ac97_t *ac97, int page_save) +{ + if (page_save >= 0) { + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); + up(&ac97->page_mutex); /* unlock paging */ + } +} + +/* volume and switch controls */ int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { int mask = (kcontrol->private_value >> 16) & 0xff; @@ -564,7 +590,9 @@ int rshift = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; - + int page_save; + + page_save = snd_ac97_page_save(ac97, reg, kcontrol); ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask; if (shift != rshift) ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask; @@ -573,6 +601,7 @@ if (shift != rshift) ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; } + snd_ac97_page_restore(ac97, page_save); return 0; } @@ -584,8 +613,10 @@ int rshift = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; + int err, page_save; unsigned short val, val2, val_mask; + page_save = snd_ac97_page_save(ac97, reg, kcontrol); val = (ucontrol->value.integer.value[0] & mask); if (invert) val = mask - val; @@ -598,7 +629,9 @@ val_mask |= mask << rshift; val |= val2 << rshift; } - return snd_ac97_update_bits(ac97, reg, val_mask, val); + err = snd_ac97_update_bits(ac97, reg, val_mask, val); + snd_ac97_page_restore(ac97, page_save); + return err; } #define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ @@ -606,40 +639,6 @@ .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } -static 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->page_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->page_mutex); /* unlock paging */ - } else - err = func(kcontrol, ucontrol); - return err; -} - -/* for rev2.3 paging */ -int snd_ac97_page_get_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_volsw); -} - -/* for rev2.3 paging */ -int snd_ac97_page_put_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_volsw); -} - 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) @@ -2331,6 +2330,35 @@ return -ENOENT; } +#if 1 +/* bind hp and master controls instead of using only hp control */ +static int bind_hp_volsw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + int err = snd_ac97_put_volsw(kcontrol, ucontrol); + if (err > 0) { + unsigned long priv_saved = kcontrol->private_value; + kcontrol->private_value = (kcontrol->private_value & ~0xff) | AC97_HEADPHONE; + snd_ac97_put_volsw(kcontrol, ucontrol); + kcontrol->private_value = priv_saved; + } + return err; +} + +/* ac97 tune: bind Master and Headphone controls */ +static int tune_hp_only(ac97_t *ac97) +{ + snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL); + snd_kcontrol_t *mvol = ctl_find(ac97, "Master Playback Volume", NULL); + if (! msw || ! mvol) + return -ENOENT; + msw->put = bind_hp_volsw_put; + mvol->put = bind_hp_volsw_put; + snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch"); + snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume"); + return 0; +} + +#else /* ac97 tune: use Headphone control as master */ static int tune_hp_only(ac97_t *ac97) { @@ -2341,6 +2369,7 @@ snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); return 0; } +#endif /* ac97 tune: swap Headphone and Master controls */ static int tune_swap_hp(ac97_t *ac97) diff -Nru a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h --- a/sound/pci/ac97/ac97_local.h 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ac97/ac97_local.h 2005-03-03 21:43:47 -08:00 @@ -23,14 +23,14 @@ */ #define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24)) -#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | ((page) << 25)) +#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26)) #define AC97_SINGLE(xname, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .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_volsw, \ - .get = snd_ac97_page_get_volsw, .put = snd_ac97_page_put_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } /* ac97_codec.c */ @@ -42,8 +42,6 @@ int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_page_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_page_put_volsw(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, const char *suffix); int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix); diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c --- a/sound/pci/ac97/ac97_patch.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ac97/ac97_patch.c 2005-03-03 21:43:47 -08:00 @@ -392,9 +392,36 @@ return 0; } +static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int err; + + down(&ac97->page_mutex); + snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); + err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, + (ucontrol->value.integer.value[0] & 1) << 4); + snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); + up(&ac97->page_mutex); + return err; +} + +static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Sigmatel Output Bias Switch", + .info = snd_ac97_info_volsw, + .get = snd_ac97_get_volsw, + .put = snd_ac97_stac9708_put_bias, + .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0), +}; + static int patch_sigmatel_stac9708_specific(ac97_t *ac97) { + int err; + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); + if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) + return err; return patch_sigmatel_stac97xx_specific(ac97); } @@ -2009,10 +2036,13 @@ { unsigned short val; - /* CM9761 has no Master and PCM volume although the register reacts */ - ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL; - snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000); - snd_ac97_write_cache(ac97, AC97_PCM, 0x8000); + /* CM9761 has no PCM volume although the register reacts */ + /* Master volume seems to have _some_ influence on the analog + * input sounds + */ + ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL; + snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808); + snd_ac97_write_cache(ac97, AC97_PCM, 0x8808); ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */ if (ac97->id == AC97_ID_CM9761_82) { @@ -2032,7 +2062,8 @@ ac97->ext_id |= AC97_EI_SPDIF; /* to be sure: we overwrite the ext status bits */ snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); - snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0209); + /* Don't set 0x0200 here. This results in the silent analog output */ + snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009); ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ /* set-up multi channel */ @@ -2057,8 +2088,10 @@ val = 0x0214; else val = 0x321c; - snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val); #endif + val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN); + val |= (1 << 4); /* front on */ + snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val); /* FIXME: set up GPIO */ snd_ac97_write_cache(ac97, 0x70, 0x0100); diff -Nru a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c --- a/sound/pci/ac97/ac97_pcm.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ac97/ac97_pcm.c 2005-03-03 21:43:47 -08:00 @@ -553,7 +553,7 @@ { ac97_bus_t *bus; int i, cidx, r, ok_flag; - unsigned int reg_ok = 0; + unsigned int reg_ok[4] = {0,0,0,0}; unsigned char reg; int err = 0; @@ -602,14 +602,14 @@ snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i); continue; } - if (reg_ok & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) + if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) continue; //printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate); err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate); if (err < 0) snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err); else - reg_ok |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); + reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); } } } diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c --- a/sound/pci/ali5451/ali5451.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ali5451/ali5451.c 2005-03-03 21:43:47 -08:00 @@ -188,7 +188,7 @@ struct snd_ali_stru_voice { unsigned int number; - int use: 1, + unsigned int use: 1, pcm: 1, midi: 1, mode: 1, @@ -199,7 +199,7 @@ snd_pcm_substream_t *substream; snd_ali_voice_t *extra; - int running: 1; + unsigned int running: 1; int eso; /* final ESO value for channel */ int count; /* runtime->period_size */ @@ -1894,7 +1894,7 @@ } #ifdef CONFIG_PM -static int ali_suspend(snd_card_t *card, unsigned int state) +static int ali_suspend(snd_card_t *card, pm_message_t state) { ali_t *chip = card->pm_private_data; ali_image_t *im; @@ -1936,7 +1936,7 @@ return 0; } -static int ali_resume(snd_card_t *card, unsigned int state) +static int ali_resume(snd_card_t *card) { ali_t *chip = card->pm_private_data; ali_image_t *im; diff -Nru a/sound/pci/atiixp.c b/sound/pci/atiixp.c --- a/sound/pci/atiixp.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/atiixp.c 2005-03-03 21:43:47 -08:00 @@ -1398,7 +1398,7 @@ /* * power management */ -static int snd_atiixp_suspend(snd_card_t *card, unsigned int state) +static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state) { atiixp_t *chip = card->pm_private_data; int i; @@ -1417,7 +1417,7 @@ return 0; } -static int snd_atiixp_resume(snd_card_t *card, unsigned int state) +static int snd_atiixp_resume(snd_card_t *card) { atiixp_t *chip = card->pm_private_data; int i; diff -Nru a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c --- a/sound/pci/atiixp_modem.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/atiixp_modem.c 2005-03-03 21:43:47 -08:00 @@ -39,7 +39,7 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; @@ -606,21 +606,20 @@ snd_pcm_runtime_t *runtime = substream->runtime; atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data; unsigned int curptr; + int timeout = 1000; - spin_lock(&chip->reg_lock); - curptr = readl(chip->remap_addr + dma->ops->dt_cur); - if (curptr < dma->buf_addr) { - snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr); - curptr = 0; - } else { + while (timeout--) { + curptr = readl(chip->remap_addr + dma->ops->dt_cur); + if (curptr < dma->buf_addr) + continue; curptr -= dma->buf_addr; - if (curptr >= dma->buf_bytes) { - snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes); - curptr = 0; - } + if (curptr >= dma->buf_bytes) + continue; + return bytes_to_frames(runtime, curptr); } - spin_unlock(&chip->reg_lock); - return bytes_to_frames(runtime, curptr); + snd_printd("atiixp-modem: invalid DMA pointer read 0x%x (buf=%x)\n", + readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); + return 0; } /* @@ -1108,7 +1107,7 @@ /* * power management */ -static int snd_atiixp_suspend(snd_card_t *card, unsigned int state) +static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state) { atiixp_t *chip = card->pm_private_data; int i; @@ -1127,7 +1126,7 @@ return 0; } -static int snd_atiixp_resume(snd_card_t *card, unsigned int state) +static int snd_atiixp_resume(snd_card_t *card) { atiixp_t *chip = card->pm_private_data; int i; diff -Nru a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c --- a/sound/pci/au88x0/au88x0_core.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/au88x0/au88x0_core.c 2005-03-03 21:43:47 -08:00 @@ -2480,7 +2480,8 @@ int i; for (i = 0; i < 32; i++) { - hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0); + /* the windows driver writes -i, so we write -i */ + hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); msleep(2); } if (0) { @@ -2502,7 +2503,7 @@ hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); } for (i = 0; i < 32; i++) { - hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0); + hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); msleep(5); } hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8); diff -Nru a/sound/pci/bt87x.c b/sound/pci/bt87x.c --- a/sound/pci/bt87x.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/bt87x.c 2005-03-03 21:43:47 -08:00 @@ -41,7 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878}," "{Brooktree,Bt879}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */ diff -Nru a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c --- a/sound/pci/ca0106/ca0106_main.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ca0106/ca0106_main.c 2005-03-03 21:43:47 -08:00 @@ -1,7 +1,7 @@ /* * Copyright (c) 2004 James Courtier-Dutton * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit - * Version: 0.0.21 + * Version: 0.0.22 * * FEATURES currently supported: * Front, Rear and Center/LFE. @@ -75,6 +75,8 @@ * 0.0.21 * Add 4 capture channels. (SPDIF only comes in on channel 0. ) * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.) + * 0.0.22 + * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 * * BUGS: * Some stability problems when unloading the snd-ca0106 kernel module. @@ -169,6 +171,7 @@ { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */ { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ + { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ { 0, "AudigyLS [Unknown]" } }; @@ -1133,7 +1136,9 @@ snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ chip->capture_source = 3; /* Set CAPTURE_SOURCE */ - if ((chip->serial == 0x10061102) || (chip->serial == 0x10071102) ) { /* The SB0410 and SB0413 use GPIO differently. */ + if ((chip->serial == 0x10061102) || + (chip->serial == 0x10071102) || + (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ @@ -1200,7 +1205,9 @@ snd_card_free(card); return err; } - if ((chip->serial != 0x10061102) && (chip->serial != 0x10071102) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */ + if ((chip->serial != 0x10061102) && + (chip->serial != 0x10071102) && + (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */ if ((err = snd_ca0106_ac97(chip)) < 0) { snd_card_free(card); return err; diff -Nru a/sound/pci/cmipci.c b/sound/pci/cmipci.c --- a/sound/pci/cmipci.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/cmipci.c 2005-03-03 21:43:47 -08:00 @@ -156,6 +156,8 @@ #define CM_CHIP_MASK2 0xff000000 #define CM_CHIP_039 0x04000000 #define CM_CHIP_039_6CH 0x01000000 +#define CM_CHIP_055 0x08000000 +#define CM_CHIP_8768 0x20000000 #define CM_TDMA_INT_EN 0x00040000 #define CM_CH1_INT_EN 0x00020000 #define CM_CH0_INT_EN 0x00010000 @@ -328,6 +330,13 @@ #define CM_REG_CH0_FRAME2 0x84 #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ +#define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */ +#define CM_CHB3D8C 0x20 /* 7.1 channels support */ +#define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */ +#define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */ +#define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */ +#define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */ +#define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */ /* * size of i/o region @@ -458,7 +467,7 @@ int opened[2]; /* open mode */ struct semaphore open_mutex; - int mixer_insensitive: 1; + unsigned int mixer_insensitive: 1; snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS]; int mixer_res_status[CM_SAVED_MIXERS]; @@ -674,7 +683,7 @@ /* */ -static unsigned int hw_channels[] = {1, 2, 4, 5, 6}; +static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8}; static snd_pcm_hw_constraint_list_t hw_constraints_channels_4 = { .count = 3, .list = hw_channels, @@ -685,6 +694,11 @@ .list = hw_channels, .mask = 0, }; +static snd_pcm_hw_constraint_list_t hw_constraints_channels_8 = { + .count = 6, + .list = hw_channels, + .mask = 0, +}; static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels) { @@ -704,13 +718,20 @@ snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); } - if (channels == 6) { + if (channels >= 6) { snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); } else { snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); } + if (cm->chip_version == 68) { + if (channels == 8) { + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); + } else { + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); + } + } spin_unlock_irq(&cm->reg_lock); } else { @@ -1504,6 +1525,7 @@ if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) return err; runtime->hw = snd_cmipci_playback; + runtime->hw.channels_max = cm->max_channels; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); cm->dig_pcm_status = cm->dig_status; return 0; @@ -1518,6 +1540,10 @@ if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0) return err; runtime->hw = snd_cmipci_capture; + if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording + runtime->hw.rate_min = 41000; + runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; + } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); return 0; } @@ -1537,8 +1563,10 @@ runtime->hw.channels_max = cm->max_channels; if (cm->max_channels == 4) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_4); - else + else if (cm->max_channels == 6) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_6); + else if (cm->max_channels == 8) + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); } @@ -2108,8 +2136,8 @@ int reg; /* register index */ unsigned int mask; /* mask bits */ unsigned int mask_on; /* mask bits to turn on */ - int is_byte: 1; /* byte access? */ - int ac3_sensitive: 1; /* access forbidden during non-audio operation? */ + unsigned int is_byte: 1; /* byte access? */ + unsigned int ac3_sensitive: 1; /* access forbidden during non-audio operation? */ } snd_cmipci_switch_args_t; static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -2346,6 +2374,11 @@ spin_unlock_irq(&cm->reg_lock); for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) { + if (cm->chip_version == 68) { // 8768 has no PCM volume + if (!strcmp(snd_cmipci_mixers[idx].name, + "PCM Playback Volume")) + continue; + } if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0) return err; } @@ -2496,30 +2529,31 @@ } } else { /* check reg 0Ch, bit 26 */ - if (detect & CM_CHIP_039) { + if (detect & CM_CHIP_8768) { + cm->chip_version = 68; + cm->max_channels = 8; + cm->can_ac3_hw = 1; + cm->has_dual_dac = 1; + cm->can_multi_ch = 1; + } else if (detect & CM_CHIP_055) { + cm->chip_version = 55; + cm->max_channels = 6; + cm->can_ac3_hw = 1; + cm->has_dual_dac = 1; + cm->can_multi_ch = 1; + } else if (detect & CM_CHIP_039) { cm->chip_version = 39; - if (detect & CM_CHIP_039_6CH) - cm->max_channels = 6; + if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ + cm->max_channels = 6; else cm->max_channels = 4; cm->can_ac3_hw = 1; cm->has_dual_dac = 1; cm->can_multi_ch = 1; } else { - cm->chip_version = 55; /* 4 or 6 channels */ - cm->max_channels = 6; - cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; - cm->can_multi_ch = 1; + printk(KERN_ERR "chip %x version not supported\n", detect); } } - - /* added -MCx suffix for chip supporting multi-channels */ - if (cm->can_multi_ch) - sprintf(cm->card->driver + strlen(cm->card->driver), - "-MC%d", cm->max_channels); - else if (cm->can_ac3_sw) - strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC"); } @@ -2623,7 +2657,15 @@ cm->max_channels = 2; cm->do_soft_ac3 = soft_ac3[dev]; - query_chip(cm); + if (pci->device != PCI_DEVICE_ID_CMEDIA_CM8338A && + pci->device != PCI_DEVICE_ID_CMEDIA_CM8338B) + query_chip(cm); + /* added -MCx suffix for chip supporting multi-channels */ + if (cm->can_multi_ch) + sprintf(cm->card->driver + strlen(cm->card->driver), + "-MC%d", cm->max_channels); + else if (cm->can_ac3_sw) + strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC"); cm->dig_status = SNDRV_PCM_DEFAULT_CON_SPDIF; cm->dig_pcm_status = SNDRV_PCM_DEFAULT_CON_SPDIF; diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c --- a/sound/pci/cs4281.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/cs4281.c 2005-03-03 21:43:47 -08:00 @@ -1376,8 +1376,8 @@ static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */ #ifdef CONFIG_PM -static int cs4281_suspend(snd_card_t *card, unsigned int state); -static int cs4281_resume(snd_card_t *card, unsigned int state); +static int cs4281_suspend(snd_card_t *card, pm_message_t state); +static int cs4281_resume(snd_card_t *card); #endif static int __devinit snd_cs4281_create(snd_card_t * card, @@ -2037,7 +2037,7 @@ #define CLKCR1_CKRA 0x00010000L -static int cs4281_suspend(snd_card_t *card, unsigned int state) +static int cs4281_suspend(snd_card_t *card, pm_message_t state) { cs4281_t *chip = card->pm_private_data; u32 ulCLK; @@ -2082,7 +2082,7 @@ return 0; } -static int cs4281_resume(snd_card_t *card, unsigned int state) +static int cs4281_resume(snd_card_t *card) { cs4281_t *chip = card->pm_private_data; unsigned int i; diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c --- a/sound/pci/cs46xx/cs46xx_lib.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/cs46xx/cs46xx_lib.c 2005-03-03 21:43:46 -08:00 @@ -3704,7 +3704,7 @@ * APM support */ #ifdef CONFIG_PM -static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state) +static int snd_cs46xx_suspend(snd_card_t *card, pm_message_t state) { cs46xx_t *chip = card->pm_private_data; int amp_saved; @@ -3728,7 +3728,7 @@ return 0; } -static int snd_cs46xx_resume(snd_card_t *card, unsigned int state) +static int snd_cs46xx_resume(snd_card_t *card) { cs46xx_t *chip = card->pm_private_data; int amp_saved; diff -Nru a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c --- a/sound/pci/emu10k1/emu10k1.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/emu10k1/emu10k1.c 2005-03-03 21:43:46 -08:00 @@ -149,6 +149,11 @@ return err; } + if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) { + snd_card_free(card); + return err; + } + if (emu->audigy) { if ((err = snd_emu10k1_audigy_midi(emu)) < 0) { snd_card_free(card); diff -Nru a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c --- a/sound/pci/emu10k1/emu10k1_callback.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/emu10k1_callback.c 2005-03-03 21:43:47 -08:00 @@ -291,7 +291,7 @@ if (vp->ch < 0) { /* allocate a voice */ emu10k1_voice_t *hwvoice; - if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 0, &hwvoice) < 0 || hwvoice == NULL) + if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL) continue; vp->ch = hwvoice->number; emu->num_voices++; diff -Nru a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c --- a/sound/pci/emu10k1/emu10k1_main.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/emu10k1_main.c 2005-03-03 21:43:47 -08:00 @@ -205,6 +205,15 @@ /* Setup SRCMulti Input Audio Enable */ outl(0x7b0000, emu->port + 0x20); outl(0xFF000000, emu->port + 0x24); + + /* Setup SPDIF Out Audio Enable */ + /* The Audigy 2 Value has a separate SPDIF out, + * so no need for a mixer switch + */ + outl(0x7a0000, emu->port + 0x20); + outl(0xFF000000, emu->port + 0x24); + tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ + outl(tmp, emu->port + A_IOCFG); } diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c --- a/sound/pci/emu10k1/emufx.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/emufx.c 2005-03-03 21:43:47 -08:00 @@ -468,10 +468,13 @@ static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr, u32 op, u32 r, u32 a, u32 x, u32 y) { + u_int32_t *code; snd_assert(*ptr < 512, return); + code = (u_int32_t *)icode->code + (*ptr) * 2; set_bit(*ptr, icode->code_valid); - icode->code[(*ptr) * 2 + 0] = ((x & 0x3ff) << 10) | (y & 0x3ff); - icode->code[(*ptr)++ * 2 + 1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff); + code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff); + code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff); + (*ptr)++; } #define OP(icode, ptr, op, r, a, x, y) \ @@ -480,10 +483,13 @@ static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr, u32 op, u32 r, u32 a, u32 x, u32 y) { + u_int32_t *code; snd_assert(*ptr < 1024, return); + code = (u_int32_t *)icode->code + (*ptr) * 2; set_bit(*ptr, icode->code_valid); - icode->code[(*ptr) * 2 + 0] = ((x & 0x7ff) << 12) | (y & 0x7ff); - icode->code[(*ptr)++ * 2 + 1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff); + code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff); + code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff); + (*ptr)++; } #define A_OP(icode, ptr, op, r, a, x, y) \ @@ -994,17 +1000,19 @@ u32 ptr; emu10k1_fx8010_code_t *icode = NULL; emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl; + u32 *gpr_map; mm_segment_t seg; spin_lock_init(&emu->fx8010.irq_lock); INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL || - (icode->gpr_map = kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL || + (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL || (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) { err = -ENOMEM; goto __err; } + gpr_map = (u32 *)icode->gpr_map; icode->tram_data_map = icode->gpr_map + 512; icode->tram_addr_map = icode->tram_data_map + 256; @@ -1065,10 +1073,10 @@ snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100); gpr += 2; - /* Music Playback */ + /* Synth Playback */ A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Playback Volume", gpr, 100); + snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100); gpr += 2; /* Wave (PCM) Capture */ @@ -1077,10 +1085,10 @@ snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0); gpr += 2; - /* Music Capture */ + /* Synth Capture */ A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Capture Volume", gpr, 0); + snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); gpr += 2; /* @@ -1331,8 +1339,8 @@ /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ /* IEC958 Optical Raw Playback Switch */ - icode->gpr_map[gpr++] = 0x1008; - icode->gpr_map[gpr++] = 0xffff0000; + gpr_map[gpr++] = 0x1008; + gpr_map[gpr++] = 0xffff0000; for (z = 0; z < 2; z++) { A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001); @@ -1358,6 +1366,11 @@ A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); #endif + /* EFX capture - capture the 16 EXTINs */ + for (z = 0; z < 16; z++) { + A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); + } + /* * ok, set up done.. */ @@ -1373,16 +1386,14 @@ seg = snd_enter_user(); icode->gpr_add_control_count = nctl; - icode->gpr_add_controls = controls; + icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls; err = snd_emu10k1_icode_poke(emu, icode); snd_leave_user(seg); __err: - if (controls != NULL) - kfree(controls); + kfree(controls); if (icode != NULL) { - if (icode->gpr_map != NULL) - kfree(icode->gpr_map); + kfree((void *)icode->gpr_map); kfree(icode); } return err; @@ -1448,6 +1459,7 @@ emu10k1_fx8010_code_t *icode; emu10k1_fx8010_pcm_t *ipcm = NULL; emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl; + u32 *gpr_map; mm_segment_t seg; spin_lock_init(&emu->fx8010.irq_lock); @@ -1455,12 +1467,13 @@ if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL) return -ENOMEM; - if ((icode->gpr_map = kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL || + if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL || (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL || (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) { err = -ENOMEM; goto __err; } + gpr_map = (u32 *)icode->gpr_map; icode->tram_data_map = icode->gpr_map + 256; icode->tram_addr_map = icode->tram_data_map + 160; @@ -1515,19 +1528,19 @@ ipcm->etram[0] = 0; ipcm->etram[1] = 1; - icode->gpr_map[gpr + 0] = 0xfffff000; - icode->gpr_map[gpr + 1] = 0xffff0000; - icode->gpr_map[gpr + 2] = 0x70000000; - icode->gpr_map[gpr + 3] = 0x00000007; - icode->gpr_map[gpr + 4] = 0x001f << 11; - icode->gpr_map[gpr + 5] = 0x001c << 11; - icode->gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ - icode->gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ - icode->gpr_map[gpr + 8] = 0x2000000 + (2<<11); - icode->gpr_map[gpr + 9] = 0x4000000 + (2<<11); - icode->gpr_map[gpr + 10] = 1<<11; - icode->gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ - icode->gpr_map[gpr + 12] = 0; + gpr_map[gpr + 0] = 0xfffff000; + gpr_map[gpr + 1] = 0xffff0000; + gpr_map[gpr + 2] = 0x70000000; + gpr_map[gpr + 3] = 0x00000007; + gpr_map[gpr + 4] = 0x001f << 11; + gpr_map[gpr + 5] = 0x001c << 11; + gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ + gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ + gpr_map[gpr + 8] = 0x2000000 + (2<<11); + gpr_map[gpr + 9] = 0x4000000 + (2<<11); + gpr_map[gpr + 10] = 1<<11; + gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ + gpr_map[gpr + 12] = 0; /* if the trigger flag is not set, skip */ /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000); @@ -1608,19 +1621,19 @@ snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0); gpr += 4; - /* Music Playback Volume */ + /* Synth Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Music Playback Volume", gpr, 100); + snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100); gpr += 2; - /* Music Capture Volume + Switch */ + /* Synth Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } - snd_emu10k1_init_stereo_control(controls + i++, "Music Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Music Capture Switch", gpr + 2, 0); + snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0); + snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0); gpr += 4; /* Surround Digital Playback Volume (renamed later without Digital) */ @@ -1930,6 +1943,24 @@ if (emu->fx8010.extout_mask & (1< tmp) { snd_BUG(); err = -EIO; @@ -1949,19 +1980,16 @@ goto __err; seg = snd_enter_user(); icode->gpr_add_control_count = i; - icode->gpr_add_controls = controls; + icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls; err = snd_emu10k1_icode_poke(emu, icode); snd_leave_user(seg); if (err >= 0) err = snd_emu10k1_ipcm_poke(emu, ipcm); __err: - if (ipcm != NULL) - kfree(ipcm); - if (controls != NULL) - kfree(controls); + kfree(ipcm); + kfree(controls); if (icode != NULL) { - if (icode->gpr_map != NULL) - kfree(icode->gpr_map); + kfree((void *)icode->gpr_map); kfree(icode); } return err; diff -Nru a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c --- a/sound/pci/emu10k1/emumixer.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/emumixer.c 2005-03-03 21:43:47 -08:00 @@ -67,6 +67,91 @@ return 0; } +static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + static char *texts[] = {"44100", "48000", "96000"}; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 3; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static int snd_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + unsigned int tmp; + unsigned long flags; + + + spin_lock_irqsave(&emu->reg_lock, flags); + tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); + switch (tmp & A_SPDIF_RATE_MASK) { + case A_SPDIF_44100: + ucontrol->value.enumerated.item[0] = 0; + break; + case A_SPDIF_48000: + ucontrol->value.enumerated.item[0] = 1; + break; + case A_SPDIF_96000: + ucontrol->value.enumerated.item[0] = 2; + break; + default: + ucontrol->value.enumerated.item[0] = 1; + } + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int change; + unsigned int reg, val, tmp; + unsigned long flags; + + switch(ucontrol->value.enumerated.item[0]) { + case 0: + val = A_SPDIF_44100; + break; + case 1: + val = A_SPDIF_48000; + break; + case 2: + val = A_SPDIF_96000; + break; + default: + val = A_SPDIF_48000; + break; + } + + + spin_lock_irqsave(&emu->reg_lock, flags); + reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); + tmp = reg & ~A_SPDIF_RATE_MASK; + tmp |= val; + if ((change = (tmp != reg))) + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + +static snd_kcontrol_new_t snd_audigy_spdif_output_rate = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Audigy SPDIF Output Sample Rate", + .count = 1, + .info = snd_audigy_spdif_output_rate_info, + .get = snd_audigy_spdif_output_rate_get, + .put = snd_audigy_spdif_output_rate_put +}; + static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { @@ -139,6 +224,8 @@ } } +/* PCM stream controls */ + static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { emu10k1_t *emu = snd_kcontrol_chip(kcontrol); @@ -345,6 +432,190 @@ .put = snd_emu10k1_attn_put }; +/* Mutichannel PCM stream controls */ + +static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = emu->audigy ? 8 : 4; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; + return 0; +} + +static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; + int idx; + int num_efx = emu->audigy ? 8 : 4; + int mask = emu->audigy ? 0x3f : 0x0f; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) + ucontrol->value.integer.value[idx] = + mix->send_routing[0][idx] & mask; + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch]; + int change = 0, idx, val; + int num_efx = emu->audigy ? 8 : 4; + int mask = emu->audigy ? 0x3f : 0x0f; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) { + val = ucontrol->value.integer.value[idx] & mask; + if (mix->send_routing[0][idx] != val) { + mix->send_routing[0][idx] = val; + change = 1; + } + } + if (change && mix->epcm->voices[ch]) + update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number, + &mix->send_routing[0][0]); + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + +static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Multichannel PCM Send Routing", + .count = 16, + .info = snd_emu10k1_efx_send_routing_info, + .get = snd_emu10k1_efx_send_routing_get, + .put = snd_emu10k1_efx_send_routing_put +}; + +static int snd_emu10k1_efx_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = emu->audigy ? 8 : 4; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 255; + return 0; +} + +static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; + int idx; + int num_efx = emu->audigy ? 8 : 4; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) + ucontrol->value.integer.value[idx] = mix->send_volume[0][idx]; + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch]; + int change = 0, idx, val; + int num_efx = emu->audigy ? 8 : 4; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) { + val = ucontrol->value.integer.value[idx] & 255; + if (mix->send_volume[0][idx] != val) { + mix->send_volume[0][idx] = val; + change = 1; + } + } + if (change && mix->epcm->voices[ch]) + update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number, + &mix->send_volume[0][0]); + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + + +static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Multichannel PCM Send Volume", + .count = 16, + .info = snd_emu10k1_efx_send_volume_info, + .get = snd_emu10k1_efx_send_volume_get, + .put = snd_emu10k1_efx_send_volume_put +}; + +static int snd_emu10k1_efx_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xffff; + return 0; +} + +static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; + unsigned long flags; + + spin_lock_irqsave(&emu->reg_lock, flags); + ucontrol->value.integer.value[0] = mix->attn[0]; + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch]; + int change = 0, val; + + spin_lock_irqsave(&emu->reg_lock, flags); + val = ucontrol->value.integer.value[0] & 0xffff; + if (mix->attn[0] != val) { + mix->attn[0] = val; + change = 1; + } + if (change && mix->epcm->voices[ch]) + snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + +static snd_kcontrol_new_t snd_emu10k1_efx_attn_control = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Multichannel PCM Volume", + .count = 16, + .info = snd_emu10k1_efx_attn_info, + .get = snd_emu10k1_efx_attn_get, + .put = snd_emu10k1_efx_attn_put +}; + static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; @@ -578,7 +849,22 @@ if ((err = snd_ctl_add(card, kctl))) return err; - /* intiailize the routing and volume table for each pcm playback stream */ + if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + + if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + + if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + + /* initialize the routing and volume table for each pcm playback stream */ for (pcm = 0; pcm < 32; pcm++) { emu10k1_pcm_mixer_t *mix; int v; @@ -598,6 +884,28 @@ mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; } + /* initialize the routing and volume table for the multichannel playback stream */ + for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) { + emu10k1_pcm_mixer_t *mix; + int v; + + mix = &emu->efx_pcm_mixer[pcm]; + mix->epcm = NULL; + + mix->send_routing[0][0] = pcm; + mix->send_routing[0][1] = (pcm == 0) ? 1 : 0; + for (v = 0; v < 2; v++) + mix->send_routing[0][2+v] = 13+v; + if (emu->audigy) + for (v = 0; v < 4; v++) + mix->send_routing[0][4+v] = 60+v; + + memset(&mix->send_volume, 0, sizeof(mix->send_volume)); + mix->send_volume[0][0] = 255; + + mix->attn[0] = 0xffff; + } + if (! emu->APS) { /* FIXME: APS has these controls? */ /* sb live! and audigy */ if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) @@ -617,6 +925,10 @@ if (emu->audigy) { if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c --- a/sound/pci/emu10k1/emupcm.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/emu10k1/emupcm.c 2005-03-03 21:43:46 -08:00 @@ -82,11 +82,28 @@ } #endif snd_pcm_period_elapsed(emu->pcm_capture_efx_substream); +} + +static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(snd_pcm_substream_t * substream) +{ + emu10k1_t *emu = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + emu10k1_pcm_t *epcm = runtime->private_data; + unsigned int ptr; + + if (!epcm->running) + return 0; + ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; + ptr += runtime->buffer_size; + ptr -= epcm->ccca_start_addr; + ptr %= runtime->buffer_size; + + return ptr; } static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices) { - int err; + int err, i; if (epcm->voices[1] != NULL && voices < 2) { snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); @@ -102,23 +119,31 @@ epcm->voices[0] = NULL; } } - err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, voices > 1, &epcm->voices[0]); + err = snd_emu10k1_voice_alloc(epcm->emu, + epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX, + voices, + &epcm->voices[0]); + if (err < 0) return err; epcm->voices[0]->epcm = epcm; if (voices > 1) { - epcm->voices[1] = &epcm->emu->voices[epcm->voices[0]->number + 1]; - epcm->voices[1]->epcm = epcm; + for (i = 1; i < voices; i++) { + epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i]; + epcm->voices[i]->epcm = epcm; + } } if (epcm->extra == NULL) { - err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, 0, &epcm->extra); + err = snd_emu10k1_voice_alloc(epcm->emu, + epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX, + 1, + &epcm->extra); if (err < 0) { // printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); - snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]); - epcm->voices[0] = NULL; - if (epcm->voices[1]) - snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); - epcm->voices[1] = NULL; + for (i = 0; i < voices; i++) { + snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); + epcm->voices[i] = NULL; + } return err; } epcm->extra->epcm = epcm; @@ -234,15 +259,21 @@ { snd_pcm_substream_t *substream = evoice->epcm->substream; snd_pcm_runtime_t *runtime = substream->runtime; - emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number]; + emu10k1_pcm_mixer_t *mix; unsigned int silent_page, tmp; int voice, stereo, w_16; unsigned char attn, send_amount[8]; unsigned char send_routing[8]; unsigned long flags; unsigned int pitch_target; + unsigned int ccis; voice = evoice->number; + if (evoice->epcm->type == PLAYBACK_EFX) + mix = &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number]; + else + mix = &emu->pcm_mixer[substream->number]; + stereo = runtime->channels == 2; w_16 = snd_pcm_format_width(runtime->format) == 16; @@ -273,10 +304,11 @@ memcpy(send_amount, &mix->send_volume[tmp][0], 8); } + ccis = stereo ? 28 : 30; + if (w_16) + ccis *= 2; + if (master) { - unsigned int ccis = stereo ? 28 : 30; - if (w_16) - ccis *= 2; evoice->epcm->ccca_start_addr = start_addr + ccis; if (extra) { start_addr += ccis; @@ -310,7 +342,12 @@ snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); pitch_target = emu10k1_calc_pitch_target(runtime->rate); - snd_emu10k1_ptr_write(emu, CCCA, voice, evoice->epcm->ccca_start_addr | + if (extra) + snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr | + emu10k1_select_interprom(pitch_target) | + (w_16 ? 0 : CCCA_8BITSELECT)); + else + snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) | emu10k1_select_interprom(pitch_target) | (w_16 ? 0 : CCCA_8BITSELECT)); // Clear filter delay memory @@ -398,6 +435,35 @@ return 0; } +static int snd_emu10k1_efx_playback_hw_free(snd_pcm_substream_t * substream) +{ + emu10k1_t *emu = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + emu10k1_pcm_t *epcm; + int i; + + if (runtime->private_data == NULL) + return 0; + epcm = runtime->private_data; + if (epcm->extra) { + snd_emu10k1_voice_free(epcm->emu, epcm->extra); + epcm->extra = NULL; + } + for (i=0; i < NUM_EFX_PLAYBACK; i++) { + if (epcm->voices[i]) { + snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); + epcm->voices[i] = NULL; + } + } + if (epcm->memblk) { + snd_emu10k1_free_pages(emu, epcm->memblk); + epcm->memblk = NULL; + epcm->start_addr = 0; + } + snd_pcm_lib_free_pages(substream); + return 0; +} + static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream) { emu10k1_t *emu = snd_pcm_substream_chip(substream); @@ -421,6 +487,59 @@ return 0; } +static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream) +{ + emu10k1_t *emu = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + emu10k1_pcm_t *epcm = runtime->private_data; + unsigned int start_addr, end_addr; + unsigned int channel_size; + int i; + + start_addr = epcm->start_addr; + end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); + + /* + * the kX driver leaves some space between voices + */ + channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK; + + snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, + start_addr, start_addr + (channel_size / 2)); + + /* only difference with the master voice is we use it for the pointer */ + snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0], + start_addr, start_addr + channel_size); + + start_addr += channel_size; + for (i = 1; i < NUM_EFX_PLAYBACK; i++) { + snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i], + start_addr, start_addr+channel_size); + start_addr += channel_size; + } + + return 0; +} + +static snd_pcm_hardware_t snd_emu10k1_efx_playback = +{ + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = NUM_EFX_PLAYBACK, + .channels_max = NUM_EFX_PLAYBACK, + .buffer_bytes_max = (64*1024), + .period_bytes_min = 64, + .period_bytes_max = (64*1024), + .periods_min = 2, + .periods_max = 2, + .fifo_size = 0, +}; + static int snd_emu10k1_capture_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { @@ -439,6 +558,7 @@ emu10k1_pcm_t *epcm = runtime->private_data; int idx; + /* zeroing the buffer size will stop capture */ snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0); switch (epcm->type) { case CAPTURE_AC97ADC: @@ -488,7 +608,7 @@ runtime = evoice->epcm->substream->runtime; voice = evoice->number; sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080; - if (runtime->channels > 1) { + if (runtime->channels == 2) { ccis = 28; cs = 4; } else { @@ -499,10 +619,11 @@ ccis *= 2; for (i = 0; i < cs; i++) snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample); + // reset cache snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0); snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra); - if (runtime->channels > 1) { + if (runtime->channels == 2) { snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0); snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra); } @@ -510,35 +631,53 @@ snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis); } -static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra) +static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra) { snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; emu10k1_pcm_mixer_t *mix; - unsigned int voice, pitch, pitch_target, tmp; unsigned int attn; + unsigned int voice, tmp; if (evoice == NULL) /* skip second voice for mono */ return; substream = evoice->epcm->substream; runtime = substream->runtime; - mix = &emu->pcm_mixer[substream->number]; voice = evoice->number; - pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8; - pitch_target = emu10k1_calc_pitch_target(runtime->rate); + + mix = evoice->epcm->type == PLAYBACK_EFX + ? &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number] + : &emu->pcm_mixer[substream->number]; + attn = extra ? 0 : 0x00ff; tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0; snd_emu10k1_ptr_write(emu, IFATN, voice, attn); snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) | 0xffff); snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) | 0xffff); - snd_emu10k1_voice_clear_loop_stop(emu, voice); - if (extra) - snd_emu10k1_voice_intr_enable(emu, voice); snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f); + snd_emu10k1_voice_clear_loop_stop(emu, voice); +} + +static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra) +{ + snd_pcm_substream_t *substream; + snd_pcm_runtime_t *runtime; + unsigned int voice, pitch, pitch_target; + + if (evoice == NULL) /* skip second voice for mono */ + return; + substream = evoice->epcm->substream; + runtime = substream->runtime; + voice = evoice->number; + + pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8; + pitch_target = emu10k1_calc_pitch_target(runtime->rate); snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target); - if (master) + if (master || evoice->epcm->type == PLAYBACK_EFX) snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target); snd_emu10k1_ptr_write(emu, IP, voice, pitch); + if (extra) + snd_emu10k1_voice_intr_enable(emu, voice); } static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice) @@ -564,7 +703,6 @@ snd_pcm_runtime_t *runtime = substream->runtime; emu10k1_pcm_t *epcm = runtime->private_data; int result = 0; - // printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); spin_lock(&emu->reg_lock); switch (cmd) { @@ -573,6 +711,9 @@ snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[0]); /* follow thru */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0); + snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0); + snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1); snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0); snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0); snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); @@ -601,10 +742,10 @@ emu10k1_pcm_t *epcm = runtime->private_data; int result = 0; - // printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream)); spin_lock(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: + // hmm this should cause full and half full interrupt to be raised? outl(epcm->capture_ipr, emu->port + IPR); snd_emu10k1_intr_enable(emu, epcm->capture_inte); // printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); @@ -680,6 +821,56 @@ return ptr; } + +static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream, + int cmd) +{ + emu10k1_t *emu = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + emu10k1_pcm_t *epcm = runtime->private_data; + int i = 0; + int result = 0; + + spin_lock(&emu->reg_lock); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + // prepare voices + for (i = 0; i < NUM_EFX_PLAYBACK; i++) { + snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[i]); + } + snd_emu10k1_playback_invalidate_cache(emu, epcm->extra); + + /* follow thru */ + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0); + snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1); + for (i = 1; i < NUM_EFX_PLAYBACK; i++) { + snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0); + } + snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0); + snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); + for (i = 1; i < NUM_EFX_PLAYBACK; i++) { + snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0); + } + epcm->running = 1; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + epcm->running = 0; + for (i = 0; i < NUM_EFX_PLAYBACK; i++) { + snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]); + } + snd_emu10k1_playback_stop_voice(emu, epcm->extra); + break; + default: + result = -EINVAL; + break; + } + spin_unlock(&emu->reg_lock); + return result; +} + + static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream) { emu10k1_t *emu = snd_pcm_substream_chip(substream); @@ -707,9 +898,9 @@ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000, .rate_min = 4000, - .rate_max = 48000, + .rate_max = 96000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (128*1024), @@ -768,6 +959,13 @@ snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate); } +static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activate) +{ + snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate); + snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate); + snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate); +} + static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime) { emu10k1_pcm_t *epcm = runtime->private_data; @@ -775,6 +973,53 @@ kfree(epcm); } +static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream) +{ + emu10k1_t *emu = snd_pcm_substream_chip(substream); + emu10k1_pcm_mixer_t *mix; + int i; + + for (i=0; i < NUM_EFX_PLAYBACK; i++) { + mix = &emu->efx_pcm_mixer[i]; + mix->epcm = NULL; + snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0); + } + return 0; +} + +static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream) +{ + emu10k1_t *emu = snd_pcm_substream_chip(substream); + emu10k1_pcm_t *epcm; + emu10k1_pcm_mixer_t *mix; + snd_pcm_runtime_t *runtime = substream->runtime; + int i; + + epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL); + if (epcm == NULL) + return -ENOMEM; + epcm->emu = emu; + epcm->type = PLAYBACK_EFX; + epcm->substream = substream; + + emu->pcm_playback_efx_substream = substream; + + runtime->private_data = epcm; + runtime->private_free = snd_emu10k1_pcm_free_substream; + runtime->hw = snd_emu10k1_efx_playback; + + for (i=0; i < NUM_EFX_PLAYBACK; i++) { + mix = &emu->efx_pcm_mixer[i]; + mix->send_routing[0][0] = i; + memset(&mix->send_volume, 0, sizeof(mix->send_volume)); + mix->send_volume[0][0] = 255; + mix->attn[0] = 0xffff; + mix->epcm = epcm; + snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1); + } + return 0; +} + static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream) { emu10k1_t *emu = snd_pcm_substream_chip(substream); @@ -969,6 +1214,19 @@ .pointer = snd_emu10k1_capture_pointer, }; +/* EFX playback */ +static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = { + .open = snd_emu10k1_efx_playback_open, + .close = snd_emu10k1_efx_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_emu10k1_playback_hw_params, + .hw_free = snd_emu10k1_efx_playback_hw_free, + .prepare = snd_emu10k1_efx_playback_prepare, + .trigger = snd_emu10k1_efx_playback_trigger, + .pointer = snd_emu10k1_efx_playback_pointer, + .page = snd_pcm_sgbuf_ops_page, +}; + static void snd_emu10k1_pcm_free(snd_pcm_t *pcm) { emu10k1_t *emu = pcm->private_data; @@ -1012,6 +1270,39 @@ return 0; } +int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm) +{ + snd_pcm_t *pcm; + snd_pcm_substream_t *substream; + int err; + + if (rpcm) + *rpcm = NULL; + + if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0) + return err; + + pcm->private_data = emu; + pcm->private_free = snd_emu10k1_pcm_free; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops); + + pcm->info_flags = 0; + pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; + strcpy(pcm->name, "EMU10K1 multichannel EFX"); + emu->pcm = pcm; + + for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) + if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) + return err; + + if (rpcm) + *rpcm = pcm; + + return 0; +} + + static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = { .open = snd_emu10k1_capture_mic_open, .close = snd_emu10k1_capture_mic_close, @@ -1114,7 +1405,7 @@ static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EFX voices mask", + .name = "Captured FX8010 Outputs", .info = snd_emu10k1_pcm_efx_voices_mask_info, .get = snd_emu10k1_pcm_efx_voices_mask_get, .put = snd_emu10k1_pcm_efx_voices_mask_put @@ -1390,8 +1681,18 @@ if (rpcm) *rpcm = pcm; - emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; - emu->efx_voices_mask[1] = 0; + /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs + * to these + */ + + /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ + if (emu->audigy) { + emu->efx_voices_mask[0] = 0; + emu->efx_voices_mask[1] = 0xffff; + } else { + emu->efx_voices_mask[0] = 0xffff0000; + emu->efx_voices_mask[1] = 0; + } snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu)); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); diff -Nru a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c --- a/sound/pci/emu10k1/emuproc.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/emuproc.c 2005-03-03 21:43:47 -08:00 @@ -140,38 +140,38 @@ /* 29 */ "???", /* 30 */ "???", /* 31 */ "???", - /* 32 */ "???", - /* 33 */ "???", - /* 34 */ "???", - /* 35 */ "???", - /* 36 */ "???", - /* 37 */ "???", - /* 38 */ "???", - /* 39 */ "???", - /* 40 */ "???", - /* 41 */ "???", - /* 42 */ "???", - /* 43 */ "???", - /* 44 */ "???", - /* 45 */ "???", - /* 46 */ "???", - /* 47 */ "???", - /* 48 */ "???", - /* 49 */ "???", - /* 50 */ "???", - /* 51 */ "???", - /* 52 */ "???", - /* 53 */ "???", - /* 54 */ "???", - /* 55 */ "???", - /* 56 */ "???", - /* 57 */ "???", - /* 58 */ "???", - /* 59 */ "???", - /* 60 */ "???", - /* 61 */ "???", - /* 62 */ "???", - /* 33 */ "???" + /* 32 */ "FXBUS2_0", + /* 33 */ "FXBUS2_1", + /* 34 */ "FXBUS2_2", + /* 35 */ "FXBUS2_3", + /* 36 */ "FXBUS2_4", + /* 37 */ "FXBUS2_5", + /* 38 */ "FXBUS2_6", + /* 39 */ "FXBUS2_7", + /* 40 */ "FXBUS2_8", + /* 41 */ "FXBUS2_9", + /* 42 */ "FXBUS2_10", + /* 43 */ "FXBUS2_11", + /* 44 */ "FXBUS2_12", + /* 45 */ "FXBUS2_13", + /* 46 */ "FXBUS2_14", + /* 47 */ "FXBUS2_15", + /* 48 */ "FXBUS2_16", + /* 49 */ "FXBUS2_17", + /* 50 */ "FXBUS2_18", + /* 51 */ "FXBUS2_19", + /* 52 */ "FXBUS2_20", + /* 53 */ "FXBUS2_21", + /* 54 */ "FXBUS2_22", + /* 55 */ "FXBUS2_23", + /* 56 */ "FXBUS2_24", + /* 57 */ "FXBUS2_25", + /* 58 */ "FXBUS2_26", + /* 59 */ "FXBUS2_27", + /* 60 */ "FXBUS2_28", + /* 61 */ "FXBUS2_29", + /* 62 */ "FXBUS2_30", + /* 63 */ "FXBUS2_31" }; emu10k1_t *emu = entry->private_data; @@ -221,7 +221,7 @@ snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); } snd_iprintf(buffer, "\nAll FX Outputs :\n"); - for (idx = 0; idx < 32; idx++) + for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++) snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1); snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1); @@ -322,6 +322,26 @@ return 0; } +static void snd_emu10k1_proc_voices_read(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + emu10k1_t *emu = entry->private_data; + emu10k1_voice_t *voice; + int idx; + + snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n"); + for (idx = 0; idx < NUM_G; idx++) { + voice = &emu->voices[idx]; + snd_iprintf(buffer, "%i\t%i\t%i\t%i\t%i\t%i\n", + idx, + voice->use, + voice->pcm, + voice->efx, + voice->synth, + voice->midi); + } +} + #ifdef CONFIG_SND_DEBUG static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) @@ -405,7 +425,7 @@ snd_iprintf(buffer, "Registers 0x%x\n", iobase); for(i = offset; i < offset+length; i++) { snd_iprintf(buffer, "%02X: ",i); - for (j = 0; j < 4; j++) { + for (j = 0; j < 64; j++) { if(iobase == 0) value = snd_ptr_read(emu, 0, i, j); else @@ -482,22 +502,22 @@ entry->c.text.write = snd_emu_proc_io_reg_write; } if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00a); + snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a); entry->c.text.write_size = 64; entry->c.text.write = snd_emu_proc_ptr_reg_write00; } if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00b); + snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b); entry->c.text.write_size = 64; entry->c.text.write = snd_emu_proc_ptr_reg_write00; } if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20a); + snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a); entry->c.text.write_size = 64; entry->c.text.write = snd_emu_proc_ptr_reg_write20; } if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20b); + snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b); entry->c.text.write_size = 64; entry->c.text.write = snd_emu_proc_ptr_reg_write20; } @@ -505,6 +525,9 @@ if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); + + if (! snd_card_proc_new(emu->card, "voices", &entry)) + snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; diff -Nru a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c --- a/sound/pci/emu10k1/io.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/io.c 2005-03-03 21:43:47 -08:00 @@ -170,6 +170,63 @@ spin_unlock_irqrestore(&emu->emu_lock, flags); } +void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicenum) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&emu->emu_lock, flags); + /* voice interrupt */ + if (voicenum >= 32) { + outl(HLIEH << 16, emu->port + PTR); + val = inl(emu->port + DATA); + val |= 1 << (voicenum - 32); + } else { + outl(HLIEL << 16, emu->port + PTR); + val = inl(emu->port + DATA); + val |= 1 << voicenum; + } + outl(val, emu->port + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); +} + +void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&emu->emu_lock, flags); + /* voice interrupt */ + if (voicenum >= 32) { + outl(HLIEH << 16, emu->port + PTR); + val = inl(emu->port + DATA); + val &= ~(1 << (voicenum - 32)); + } else { + outl(HLIEL << 16, emu->port + PTR); + val = inl(emu->port + DATA); + val &= ~(1 << voicenum); + } + outl(val, emu->port + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); +} + +void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum) +{ + unsigned long flags; + + spin_lock_irqsave(&emu->emu_lock, flags); + /* voice interrupt */ + if (voicenum >= 32) { + outl(HLIPH << 16, emu->port + PTR); + voicenum = 1 << (voicenum - 32); + } else { + outl(HLIPL << 16, emu->port + PTR); + voicenum = 1 << voicenum; + } + outl(voicenum, emu->port + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); +} + void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum) { unsigned long flags; diff -Nru a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c --- a/sound/pci/emu10k1/irq.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/irq.c 2005-03-03 21:43:47 -08:00 @@ -73,6 +73,21 @@ val >>= 1; pvoice++; } + val = snd_emu10k1_ptr_read(emu, HLIPL, 0); + for (voice = 0; voice <= voice_max; voice++) { + if (voice == 0x20) + val = snd_emu10k1_ptr_read(emu, HLIPH, 0); + if (val & 1) { + if (pvoice->use && pvoice->interrupt != NULL) { + pvoice->interrupt(emu, pvoice); + snd_emu10k1_voice_half_loop_intr_ack(emu, voice); + } else { + snd_emu10k1_voice_half_loop_intr_disable(emu, voice); + } + } + val >>= 1; + pvoice++; + } status &= ~IPR_CHANNELLOOP; } status &= ~IPR_CHANNELNUMBERMASK; diff -Nru a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c --- a/sound/pci/emu10k1/voice.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/emu10k1/voice.c 2005-03-03 21:43:47 -08:00 @@ -1,8 +1,11 @@ /* * Copyright (c) by Jaroslav Kysela * Creative Labs, Inc. + * Lee Revell * Routines for control of EMU10K1 chips - voice manager * + * Rewrote voice allocator for multichannel support - rlrevell 12/2004 + * * BUGS: * -- * @@ -30,25 +33,68 @@ #include #include -static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice) +/* Previously the voice allocator started at 0 every time. The new voice + * allocator uses a round robin scheme. The next free voice is tracked in + * the card record and each allocation begins where the last left off. The + * hardware requires stereo interleaved voices be aligned to an even/odd + * boundary. For multichannel voice allocation we ensure than the block of + * voices does not cross the 32 voice boundary. This simplifies the + * multichannel support and ensures we can use a single write to the + * (set|clear)_loop_stop registers. Otherwise (for example) the voices would + * get out of sync when pausing/resuming a stream. + * --rlrevell + */ + +static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice) { - emu10k1_voice_t *voice, *voice2; - int idx; + emu10k1_voice_t *voice; + int i, j, k, first_voice, last_voice, skip; *rvoice = NULL; - for (idx = 0; idx < 64; idx += pair ? 2 : 1) { - voice = &emu->voices[idx]; - voice2 = pair ? &emu->voices[idx+1] : NULL; - if (voice->use || (voice2 && voice2->use)) + first_voice = last_voice = 0; + for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { + // printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice); + i %= NUM_G; + + /* stereo voices must be even/odd */ + if ((number == 2) && (i % 2)) { + i++; continue; + } + + /* make sure the block of voices does not cross the 32 voice boundary */ + //if (((i % 32) + number) > 32) + // continue; + + skip = 0; + for (k = 0; k < number; k++) { + voice = &emu->voices[(i+k) % NUM_G]; + if (voice->use) + skip = 1; + } + if (!skip) { + // printk("allocated voice %d\n", i); + first_voice = i; + last_voice = (i + number) % NUM_G; + emu->next_free_voice = last_voice; + break; + } + } + + if (first_voice == last_voice) { + printk("BUG (or not enough voices), number %d, next free %d!\n", + number, + emu->next_free_voice); + return -ENOMEM; + } + + for (i=0; i < number; i++) { + voice = &emu->voices[(first_voice + i) % NUM_G]; + // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number); voice->use = 1; - if (voice2) - voice2->use = 1; switch (type) { case EMU10K1_PCM: voice->pcm = 1; - if (voice2) - voice2->pcm = 1; break; case EMU10K1_SYNTH: voice->synth = 1; @@ -56,26 +102,27 @@ case EMU10K1_MIDI: voice->midi = 1; break; + case EMU10K1_EFX: + voice->efx = 1; + break; } - // printk("voice alloc - %i, pair = %i\n", voice->number, pair); - *rvoice = voice; - return 0; } - return -ENOMEM; + *rvoice = &emu->voices[first_voice]; + return 0; } -int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice) +int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice) { unsigned long flags; int result; snd_assert(rvoice != NULL, return -EINVAL); - snd_assert(!pair || type == EMU10K1_PCM, return -EINVAL); + snd_assert(number, return -EINVAL); spin_lock_irqsave(&emu->voice_lock, flags); for (;;) { - result = voice_alloc(emu, type, pair, rvoice); - if (result == 0 || type != EMU10K1_PCM) + result = voice_alloc(emu, type, number, rvoice); + if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI) break; /* free a voice from synth */ @@ -84,7 +131,7 @@ if (result >= 0) { emu10k1_voice_t *pvoice = &emu->voices[result]; pvoice->interrupt = NULL; - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; + pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; pvoice->epcm = NULL; } } @@ -103,7 +150,7 @@ snd_assert(pvoice != NULL, return -EINVAL); spin_lock_irqsave(&emu->voice_lock, flags); pvoice->interrupt = NULL; - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; + pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; pvoice->epcm = NULL; snd_emu10k1_voice_init(emu, pvoice->number); spin_unlock_irqrestore(&emu->voice_lock, flags); diff -Nru a/sound/pci/es1938.c b/sound/pci/es1938.c --- a/sound/pci/es1938.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/es1938.c 2005-03-03 21:43:47 -08:00 @@ -1381,7 +1381,7 @@ }; -static int es1938_suspend(snd_card_t *card, unsigned int state) +static int es1938_suspend(snd_card_t *card, pm_message_t state) { es1938_t *chip = card->pm_private_data; unsigned char *s, *d; @@ -1398,7 +1398,7 @@ return 0; } -static int es1938_resume(snd_card_t *card, unsigned int state) +static int es1938_resume(snd_card_t *card) { es1938_t *chip = card->pm_private_data; unsigned char *s, *d; diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c --- a/sound/pci/es1968.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/es1968.c 2005-03-03 21:43:47 -08:00 @@ -2404,7 +2404,7 @@ /* * PM support */ -static int es1968_suspend(snd_card_t *card, unsigned int state) +static int es1968_suspend(snd_card_t *card, pm_message_t state) { es1968_t *chip = card->pm_private_data; @@ -2419,7 +2419,7 @@ return 0; } -static int es1968_resume(snd_card_t *card, unsigned int state) +static int es1968_resume(snd_card_t *card) { es1968_t *chip = card->pm_private_data; diff -Nru a/sound/pci/fm801.c b/sound/pci/fm801.c --- a/sound/pci/fm801.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/fm801.c 2005-03-03 21:43:47 -08:00 @@ -64,7 +64,7 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); -module_param_array(tea575x_tuner, bool, NULL, 0444); +module_param_array(tea575x_tuner, int, NULL, 0444); MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner."); /* diff -Nru a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/Makefile 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,7 @@ +snd-hda-intel-objs := hda_intel.o +snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o +ifdef CONFIG_PROC_FS +snd-hda-codec-objs += hda_proc.o +endif + +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o snd-hda-codec.o diff -Nru a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_codec.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,1850 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * Copyright (c) 2004 Takashi Iwai + * + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver 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 +#include +#include +#include +#include +#include +#include +#include "hda_codec.h" +#include +#include +#include "hda_local.h" + + +MODULE_AUTHOR("Takashi Iwai "); +MODULE_DESCRIPTION("Universal interface for High Definition Audio Codec"); +MODULE_LICENSE("GPL"); + + +/* + * vendor / preset table + */ + +struct hda_vendor_id { + unsigned int id; + const char *name; +}; + +/* codec vendor labels */ +static struct hda_vendor_id hda_vendor_ids[] = { + { 0x10ec, "Realtek" }, + { 0x434d, "C-Media" }, + {} /* terminator */ +}; + +/* codec presets */ +#include "hda_patch.h" + + +/** + * snd_hda_codec_read - send a command and get the response + * @codec: the HDA codec + * @nid: NID to send the command + * @direct: direct flag + * @verb: the verb to send + * @parm: the parameter for the verb + * + * Send a single command and read the corresponding response. + * + * Returns the obtained response value, or -1 for an error. + */ +unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm) +{ + unsigned int res; + down(&codec->bus->cmd_mutex); + if (! codec->bus->ops.command(codec, nid, direct, verb, parm)) + res = codec->bus->ops.get_response(codec); + else + res = (unsigned int)-1; + up(&codec->bus->cmd_mutex); + return res; +} + +/** + * snd_hda_codec_write - send a single command without waiting for response + * @codec: the HDA codec + * @nid: NID to send the command + * @direct: direct flag + * @verb: the verb to send + * @parm: the parameter for the verb + * + * Send a single command without waiting for response. + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm) +{ + int err; + down(&codec->bus->cmd_mutex); + err = codec->bus->ops.command(codec, nid, direct, verb, parm); + up(&codec->bus->cmd_mutex); + return err; +} + +/** + * snd_hda_sequence_write - sequence writes + * @codec: the HDA codec + * @seq: VERB array to send + * + * Send the commands sequentially from the given array. + * The array must be terminated with NID=0. + */ +void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) +{ + for (; seq->nid; seq++) + snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); +} + +/** + * snd_hda_get_sub_nodes - get the range of sub nodes + * @codec: the HDA codec + * @nid: NID to parse + * @start_id: the pointer to store the start NID + * + * Parse the NID and store the start NID of its sub-nodes. + * Returns the number of sub-nodes. + */ +int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id) +{ + unsigned int parm; + + parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); + *start_id = (parm >> 16) & 0x7fff; + return (int)(parm & 0x7fff); +} + +/** + * snd_hda_get_connections - get connection list + * @codec: the HDA codec + * @nid: NID to parse + * @conn_list: connection list array + * @max_conns: max. number of connections to store + * + * Parses the connection list of the given widget and stores the list + * of NIDs. + * + * Returns the number of connections, or a negative error code. + */ +int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, + hda_nid_t *conn_list, int max_conns) +{ + unsigned int parm; + int i, j, conn_len, num_tupples, conns; + unsigned int shift, num_elems, mask; + + snd_assert(conn_list && max_conns > 0, return -EINVAL); + + parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); + if (parm & AC_CLIST_LONG) { + /* long form */ + shift = 16; + num_elems = 2; + } else { + /* short form */ + shift = 8; + num_elems = 4; + } + conn_len = parm & AC_CLIST_LENGTH; + num_tupples = num_elems / 2; + mask = (1 << (shift-1)) - 1; + + if (! conn_len) + return 0; /* no connection */ + + if (conn_len == 1) { + /* single connection */ + parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, 0); + conn_list[0] = parm & mask; + return 1; + } + + /* multi connection */ + conns = 0; + for (i = 0; i < conn_len; i += num_elems) { + parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, i); + for (j = 0; j < num_tupples; j++) { + int range_val; + hda_nid_t val1, val2, n; + range_val = parm & (1 << (shift-1)); /* ranges */ + val1 = parm & mask; + parm >>= shift; + val2 = parm & mask; + parm >>= shift; + if (range_val) { + /* ranges between val1 and val2 */ + if (val1 > val2) { + snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", val1, val2); + continue; + } + for (n = val1; n <= val2; n++) { + if (conns >= max_conns) + return -EINVAL; + conn_list[conns++] = n; + } + } else { + if (! val1) + break; + if (conns >= max_conns) + return -EINVAL; + conn_list[conns++] = val1; + if (! val2) + break; + if (conns >= max_conns) + return -EINVAL; + conn_list[conns++] = val2; + } + } + } + return conns; +} + + +/** + * snd_hda_queue_unsol_event - add an unsolicited event to queue + * @bus: the BUS + * @res: unsolicited event (lower 32bit of RIRB entry) + * @res_ex: codec addr and flags (upper 32bit or RIRB entry) + * + * Adds the given event to the queue. The events are processed in + * the workqueue asynchronously. Call this function in the interrupt + * hanlder when RIRB receives an unsolicited event. + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) +{ + struct hda_bus_unsolicited *unsol; + unsigned int wp; + + if ((unsol = bus->unsol) == NULL) + return 0; + + wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE; + unsol->wp = wp; + + wp <<= 1; + unsol->queue[wp] = res; + unsol->queue[wp + 1] = res_ex; + + queue_work(unsol->workq, &unsol->work); + + return 0; +} + +/* + * process queueud unsolicited events + */ +static void process_unsol_events(void *data) +{ + struct hda_bus *bus = data; + struct hda_bus_unsolicited *unsol = bus->unsol; + struct hda_codec *codec; + unsigned int rp, caddr, res; + + while (unsol->rp != unsol->wp) { + rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE; + unsol->rp = rp; + rp <<= 1; + res = unsol->queue[rp]; + caddr = unsol->queue[rp + 1]; + if (! (caddr & (1 << 4))) /* no unsolicited event? */ + continue; + codec = bus->caddr_tbl[caddr & 0x0f]; + if (codec && codec->patch_ops.unsol_event) + codec->patch_ops.unsol_event(codec, res); + } +} + +/* + * initialize unsolicited queue + */ +static int init_unsol_queue(struct hda_bus *bus) +{ + struct hda_bus_unsolicited *unsol; + + unsol = kcalloc(1, sizeof(*unsol), GFP_KERNEL); + if (! unsol) { + snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); + return -ENOMEM; + } + unsol->workq = create_workqueue("hda_codec"); + if (! unsol->workq) { + snd_printk(KERN_ERR "hda_codec: can't create workqueue\n"); + kfree(unsol); + return -ENOMEM; + } + INIT_WORK(&unsol->work, process_unsol_events, bus); + bus->unsol = unsol; + return 0; +} + +/* + * destructor + */ +static void snd_hda_codec_free(struct hda_codec *codec); + +static int snd_hda_bus_free(struct hda_bus *bus) +{ + struct list_head *p, *n; + + if (! bus) + return 0; + if (bus->unsol) { + destroy_workqueue(bus->unsol->workq); + kfree(bus->unsol); + } + list_for_each_safe(p, n, &bus->codec_list) { + struct hda_codec *codec = list_entry(p, struct hda_codec, list); + snd_hda_codec_free(codec); + } + if (bus->ops.private_free) + bus->ops.private_free(bus); + kfree(bus); + return 0; +} + +static int snd_hda_bus_dev_free(snd_device_t *device) +{ + struct hda_bus *bus = device->device_data; + return snd_hda_bus_free(bus); +} + +/** + * snd_hda_bus_new - create a HDA bus + * @card: the card entry + * @temp: the template for hda_bus information + * @busp: the pointer to store the created bus instance + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp, + struct hda_bus **busp) +{ + struct hda_bus *bus; + int err; + static snd_device_ops_t dev_ops = { + .dev_free = snd_hda_bus_dev_free, + }; + + snd_assert(temp, return -EINVAL); + snd_assert(temp->ops.command && temp->ops.get_response, return -EINVAL); + + if (busp) + *busp = NULL; + + bus = kcalloc(1, sizeof(*bus), GFP_KERNEL); + if (bus == NULL) { + snd_printk(KERN_ERR "can't allocate struct hda_bus\n"); + return -ENOMEM; + } + + bus->card = card; + bus->private_data = temp->private_data; + bus->pci = temp->pci; + bus->modelname = temp->modelname; + bus->ops = temp->ops; + + init_MUTEX(&bus->cmd_mutex); + INIT_LIST_HEAD(&bus->codec_list); + + init_unsol_queue(bus); + + if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { + snd_hda_bus_free(bus); + return err; + } + if (busp) + *busp = bus; + return 0; +} + + +/* + * find a matching codec preset + */ +static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec) +{ + const struct hda_codec_preset **tbl, *preset; + + for (tbl = hda_preset_tables; *tbl; tbl++) { + for (preset = *tbl; preset->id; preset++) { + u32 mask = preset->mask; + if (! mask) + mask = ~0; + if (preset->id == (codec->vendor_id & mask)) + return preset; + } + } + return NULL; +} + +/* + * snd_hda_get_codec_name - store the codec name + */ +void snd_hda_get_codec_name(struct hda_codec *codec, + char *name, int namelen) +{ + const struct hda_vendor_id *c; + const char *vendor = NULL; + u16 vendor_id = codec->vendor_id >> 16; + char tmp[16]; + + for (c = hda_vendor_ids; c->id; c++) { + if (c->id == vendor_id) { + vendor = c->name; + break; + } + } + if (! vendor) { + sprintf(tmp, "Generic %04x", vendor_id); + vendor = tmp; + } + if (codec->preset && codec->preset->name) + snprintf(name, namelen, "%s %s", vendor, codec->preset->name); + else + snprintf(name, namelen, "%s ID %x", vendor, codec->vendor_id & 0xffff); +} + +/* + * look for an AFG node + * + * return 0 if not found + */ +static int look_for_afg_node(struct hda_codec *codec) +{ + int i, total_nodes; + hda_nid_t nid; + + total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); + for (i = 0; i < total_nodes; i++, nid++) { + if ((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff) == + AC_GRP_AUDIO_FUNCTION) + return nid; + } + return 0; +} + +/* + * codec destructor + */ +static void snd_hda_codec_free(struct hda_codec *codec) +{ + if (! codec) + return; + list_del(&codec->list); + codec->bus->caddr_tbl[codec->addr] = NULL; + if (codec->patch_ops.free) + codec->patch_ops.free(codec); + kfree(codec); +} + +static void init_amp_hash(struct hda_codec *codec); + +/** + * snd_hda_codec_new - create a HDA codec + * @bus: the bus to assign + * @codec_addr: the codec address + * @codecp: the pointer to store the generated codec + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, + struct hda_codec **codecp) +{ + struct hda_codec *codec; + char component[13]; + int err; + + snd_assert(bus, return -EINVAL); + snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL); + + if (bus->caddr_tbl[codec_addr]) { + snd_printk(KERN_ERR "hda_codec: address 0x%x is already occupied\n", codec_addr); + return -EBUSY; + } + + codec = kcalloc(1, sizeof(*codec), GFP_KERNEL); + if (codec == NULL) { + snd_printk(KERN_ERR "can't allocate struct hda_codec\n"); + return -ENOMEM; + } + + codec->bus = bus; + codec->addr = codec_addr; + init_MUTEX(&codec->spdif_mutex); + init_amp_hash(codec); + + list_add_tail(&codec->list, &bus->codec_list); + bus->caddr_tbl[codec_addr] = codec; + + codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); + codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); + codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); + + /* FIXME: support for multiple AFGs? */ + codec->afg = look_for_afg_node(codec); + if (! codec->afg) { + snd_printk(KERN_ERR "hda_codec: no AFG node found\n"); + snd_hda_codec_free(codec); + return -ENODEV; + } + + codec->preset = find_codec_preset(codec); + if (! *bus->card->mixername) + snd_hda_get_codec_name(codec, bus->card->mixername, + sizeof(bus->card->mixername)); + + if (codec->preset && codec->preset->patch) + err = codec->preset->patch(codec); + else + err = snd_hda_parse_generic_codec(codec); + if (err < 0) { + snd_hda_codec_free(codec); + return err; + } + + snd_hda_codec_proc_new(codec); + + sprintf(component, "HDA:%08x", codec->vendor_id); + snd_component_add(codec->bus->card, component); + + if (codecp) + *codecp = codec; + return 0; +} + +/** + * snd_hda_codec_setup_stream - set up the codec for streaming + * @codec: the CODEC to set up + * @nid: the NID to set up + * @stream_tag: stream tag to pass, it's between 0x1 and 0xf. + * @channel_id: channel id to pass, zero based. + * @format: stream format. + */ +void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, + int channel_id, int format) +{ + snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", + nid, stream_tag, channel_id, format); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, + (stream_tag << 4) | channel_id); + msleep(1); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); +} + + +/* + * amp access functions + */ + +#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64) +#define INFO_AMP_CAPS (1<<0) +#define INFO_AMP_VOL (1<<1) + +/* initialize the hash table */ +static void init_amp_hash(struct hda_codec *codec) +{ + memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash)); + codec->num_amp_entries = 0; +} + +/* query the hash. allocate an entry if not found. */ +static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) +{ + u16 idx = key % (u16)ARRAY_SIZE(codec->amp_hash); + u16 cur = codec->amp_hash[idx]; + struct hda_amp_info *info; + + while (cur != 0xffff) { + info = &codec->amp_info[cur]; + if (info->key == key) + return info; + cur = info->next; + } + + /* add a new hash entry */ + if (codec->num_amp_entries >= ARRAY_SIZE(codec->amp_info)) { + snd_printk(KERN_ERR "hda_codec: Tooooo many amps!\n"); + return NULL; + } + cur = codec->num_amp_entries++; + info = &codec->amp_info[cur]; + info->key = key; + info->status = 0; /* not initialized yet */ + info->next = codec->amp_hash[idx]; + codec->amp_hash[idx] = cur; + + return info; +} + +/* + * query AMP capabilities for the given widget and direction + */ +static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) +{ + struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); + + if (! info) + return 0; + if (! (info->status & INFO_AMP_CAPS)) { + info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ? + AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); + info->status |= INFO_AMP_CAPS; + } + return info->amp_caps; +} + +/* + * read the current volume to info + * if the cache exists, read from the cache. + */ +static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, + hda_nid_t nid, int ch, int direction, int index) +{ + u32 val, parm; + + if (info->status & (INFO_AMP_VOL << ch)) + return; + + parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; + parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; + parm |= index; + val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm); + info->vol[ch] = val & 0xff; + info->status |= INFO_AMP_VOL << ch; +} + +/* + * write the current volume in info to the h/w + */ +static void put_vol_mute(struct hda_codec *codec, + hda_nid_t nid, int ch, int direction, int index, int val) +{ + u32 parm; + + parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT; + parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT; + parm |= index << AC_AMP_SET_INDEX_SHIFT; + parm |= val; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); +} + +/* + * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. + */ +int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) +{ + struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); + if (! info) + return 0; + get_vol_mute(codec, info, nid, ch, direction, index); + return info->vol[ch]; +} + +int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val) +{ + struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); + if (! info) + return 0; + get_vol_mute(codec, info, nid, ch, direction, idx); + if (info->vol[ch] == val && ! codec->in_resume) + return 0; + put_vol_mute(codec, nid, ch, direction, idx, val); + info->vol[ch] = val; + return 1; +} + + +/* + * AMP control callbacks + */ +/* retrieve parameters from private_value */ +#define get_amp_nid(kc) ((kc)->private_value & 0xffff) +#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) +#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) +#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) + +/* volume */ +int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + u16 nid = get_amp_nid(kcontrol); + u8 chs = get_amp_channels(kcontrol); + int dir = get_amp_direction(kcontrol); + u32 caps; + + caps = query_amp_caps(codec, nid, dir); + caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; /* num steps */ + if (! caps) { + printk(KERN_WARNING "hda_codec: num_steps = 0 for NID=0x%x\n", nid); + return -EINVAL; + } + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = chs == 3 ? 2 : 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = caps; + return 0; +} + +int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = get_amp_nid(kcontrol); + int chs = get_amp_channels(kcontrol); + int dir = get_amp_direction(kcontrol); + int idx = get_amp_index(kcontrol); + long *valp = ucontrol->value.integer.value; + + if (chs & 1) + *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f; + if (chs & 2) + *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f; + return 0; +} + +int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = get_amp_nid(kcontrol); + int chs = get_amp_channels(kcontrol); + int dir = get_amp_direction(kcontrol); + int idx = get_amp_index(kcontrol); + int val; + long *valp = ucontrol->value.integer.value; + int change = 0; + + if (chs & 1) { + val = *valp & 0x7f; + val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80; + change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val); + valp++; + } + if (chs & 2) { + val = *valp & 0x7f; + val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80; + change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val); + } + return change; +} + +/* switch */ +int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + int chs = get_amp_channels(kcontrol); + + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = chs == 3 ? 2 : 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = get_amp_nid(kcontrol); + int chs = get_amp_channels(kcontrol); + int dir = get_amp_direction(kcontrol); + int idx = get_amp_index(kcontrol); + long *valp = ucontrol->value.integer.value; + + if (chs & 1) + *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80) ? 0 : 1; + if (chs & 2) + *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80) ? 0 : 1; + return 0; +} + +int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = get_amp_nid(kcontrol); + int chs = get_amp_channels(kcontrol); + int dir = get_amp_direction(kcontrol); + int idx = get_amp_index(kcontrol); + int val; + long *valp = ucontrol->value.integer.value; + int change = 0; + + if (chs & 1) { + val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f; + val |= *valp ? 0 : 0x80; + change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val); + valp++; + } + if (chs & 2) { + val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f; + val |= *valp ? 0 : 0x80; + change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val); + } + return change; +} + +/* + * SPDIF out controls + */ + +static int snd_hda_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +static int snd_hda_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | + IEC958_AES0_NONAUDIO | + IEC958_AES0_CON_EMPHASIS_5015 | + IEC958_AES0_CON_NOT_COPYRIGHT; + ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY | + IEC958_AES1_CON_ORIGINAL; + return 0; +} + +static int snd_hda_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | + IEC958_AES0_NONAUDIO | + IEC958_AES0_PRO_EMPHASIS_5015; + return 0; +} + +static int snd_hda_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + + ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff; + ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff; + ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff; + ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff; + + return 0; +} + +/* convert from SPDIF status bits to HDA SPDIF bits + * bit 0 (DigEn) is always set zero (to be filled later) + */ +static unsigned short convert_from_spdif_status(unsigned int sbits) +{ + unsigned short val = 0; + + if (sbits & IEC958_AES0_PROFESSIONAL) + val |= 1 << 6; + if (sbits & IEC958_AES0_NONAUDIO) + val |= 1 << 5; + if (sbits & IEC958_AES0_PROFESSIONAL) { + if ((sbits & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015) + val |= 1 << 3; + } else { + if ((sbits & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015) + val |= 1 << 3; + if (! (sbits & IEC958_AES0_CON_NOT_COPYRIGHT)) + val |= 1 << 4; + if (sbits & (IEC958_AES1_CON_ORIGINAL << 8)) + val |= 1 << 7; + val |= sbits & (IEC958_AES1_CON_CATEGORY << 8); + } + return val; +} + +/* convert to SPDIF status bits from HDA SPDIF bits + */ +static unsigned int convert_to_spdif_status(unsigned short val) +{ + unsigned int sbits = 0; + + if (val & (1 << 5)) + sbits |= IEC958_AES0_NONAUDIO; + if (val & (1 << 6)) + sbits |= IEC958_AES0_PROFESSIONAL; + if (sbits & IEC958_AES0_PROFESSIONAL) { + if (sbits & (1 << 3)) + sbits |= IEC958_AES0_PRO_EMPHASIS_5015; + } else { + if (val & (1 << 3)) + sbits |= IEC958_AES0_CON_EMPHASIS_5015; + if (! (val & (1 << 4))) + sbits |= IEC958_AES0_CON_NOT_COPYRIGHT; + if (val & (1 << 7)) + sbits |= (IEC958_AES1_CON_ORIGINAL << 8); + sbits |= val & (0x7f << 8); + } + return sbits; +} + +static int snd_hda_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = kcontrol->private_value; + unsigned short val; + int change; + + down(&codec->spdif_mutex); + codec->spdif_status = ucontrol->value.iec958.status[0] | + ((unsigned int)ucontrol->value.iec958.status[1] << 8) | + ((unsigned int)ucontrol->value.iec958.status[2] << 16) | + ((unsigned int)ucontrol->value.iec958.status[3] << 24); + val = convert_from_spdif_status(codec->spdif_status); + val |= codec->spdif_ctls & 1; + change = codec->spdif_ctls != val; + codec->spdif_ctls = val; + + if (change || codec->in_resume) { + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8); + } + + up(&codec->spdif_mutex); + return change; +} + +static int snd_hda_spdif_out_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_hda_spdif_out_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = codec->spdif_ctls & 1; + return 0; +} + +static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = kcontrol->private_value; + unsigned short val; + int change; + + down(&codec->spdif_mutex); + val = codec->spdif_ctls & ~1; + if (ucontrol->value.integer.value[0]) + val |= 1; + change = codec->spdif_ctls != val; + if (change || codec->in_resume) { + codec->spdif_ctls = val; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); + } + up(&codec->spdif_mutex); + return change; +} + +static snd_kcontrol_new_t dig_mixes[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .info = snd_hda_spdif_mask_info, + .get = snd_hda_spdif_cmask_get, + }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), + .info = snd_hda_spdif_mask_info, + .get = snd_hda_spdif_pmask_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .info = snd_hda_spdif_mask_info, + .get = snd_hda_spdif_default_get, + .put = snd_hda_spdif_default_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), + .info = snd_hda_spdif_out_switch_info, + .get = snd_hda_spdif_out_switch_get, + .put = snd_hda_spdif_out_switch_put, + }, + { } /* end */ +}; + +/** + * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls + * @codec: the HDA codec + * @nid: audio out widget NID + * + * Creates controls related with the SPDIF output. + * Called from each patch supporting the SPDIF out. + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) +{ + int err; + snd_kcontrol_t *kctl; + snd_kcontrol_new_t *dig_mix; + + for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { + kctl = snd_ctl_new1(dig_mix, codec); + kctl->private_value = nid; + if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) + return err; + } + codec->spdif_ctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); + codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); + return 0; +} + +/* + * SPDIF input + */ + +#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info + +static int snd_hda_spdif_in_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = codec->spdif_in_enable; + return 0; +} + +static int snd_hda_spdif_in_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = kcontrol->private_value; + unsigned int val = !!ucontrol->value.integer.value[0]; + int change; + + down(&codec->spdif_mutex); + change = codec->spdif_in_enable != val; + if (change || codec->in_resume) { + codec->spdif_in_enable = val; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); + } + up(&codec->spdif_mutex); + return change; +} + +static int snd_hda_spdif_in_status_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = kcontrol->private_value; + unsigned short val; + unsigned int sbits; + + val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); + sbits = convert_to_spdif_status(val); + ucontrol->value.iec958.status[0] = sbits; + ucontrol->value.iec958.status[1] = sbits >> 8; + ucontrol->value.iec958.status[2] = sbits >> 16; + ucontrol->value.iec958.status[3] = sbits >> 24; + return 0; +} + +static snd_kcontrol_new_t dig_in_ctls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), + .info = snd_hda_spdif_in_switch_info, + .get = snd_hda_spdif_in_switch_get, + .put = snd_hda_spdif_in_switch_put, + }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), + .info = snd_hda_spdif_mask_info, + .get = snd_hda_spdif_in_status_get, + }, + { } /* end */ +}; + +/** + * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls + * @codec: the HDA codec + * @nid: audio in widget NID + * + * Creates controls related with the SPDIF input. + * Called from each patch supporting the SPDIF in. + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) +{ + int err; + snd_kcontrol_t *kctl; + snd_kcontrol_new_t *dig_mix; + + for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { + kctl = snd_ctl_new1(dig_mix, codec); + kctl->private_value = nid; + if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) + return err; + } + codec->spdif_in_enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & 1; + return 0; +} + + +/** + * snd_hda_build_controls - build mixer controls + * @bus: the BUS + * + * Creates mixer controls for each codec included in the bus. + * + * Returns 0 if successful, otherwise a negative error code. + */ +int snd_hda_build_controls(struct hda_bus *bus) +{ + struct list_head *p; + + /* build controls */ + list_for_each(p, &bus->codec_list) { + struct hda_codec *codec = list_entry(p, struct hda_codec, list); + int err; + if (! codec->patch_ops.build_controls) + continue; + err = codec->patch_ops.build_controls(codec); + if (err < 0) + return err; + } + + /* initialize */ + list_for_each(p, &bus->codec_list) { + struct hda_codec *codec = list_entry(p, struct hda_codec, list); + int err; + if (! codec->patch_ops.init) + continue; + err = codec->patch_ops.init(codec); + if (err < 0) + return err; + } + return 0; +} + + +/* + * stream formats + */ +static unsigned int rate_bits[][3] = { + /* rate in Hz, ALSA rate bitmask, HDA format value */ + { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ + { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ + { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ + { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */ + { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */ + { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */ + { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */ + { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */ + { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ + { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ + { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ + { 0 } +}; + +/** + * snd_hda_calc_stream_format - calculate format bitset + * @rate: the sample rate + * @channels: the number of channels + * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) + * @maxbps: the max. bps + * + * Calculate the format bitset from the given rate, channels and th PCM format. + * + * Return zero if invalid. + */ +unsigned int snd_hda_calc_stream_format(unsigned int rate, + unsigned int channels, + unsigned int format, + unsigned int maxbps) +{ + int i; + unsigned int val = 0; + + for (i = 0; rate_bits[i][0]; i++) + if (rate_bits[i][0] == rate) { + val = rate_bits[i][2]; + break; + } + if (! rate_bits[i][0]) { + snd_printdd("invalid rate %d\n", rate); + return 0; + } + + if (channels == 0 || channels > 8) { + snd_printdd("invalid channels %d\n", channels); + return 0; + } + val |= channels - 1; + + switch (snd_pcm_format_width(format)) { + case 8: val |= 0x00; break; + case 16: val |= 0x10; break; + case 20: + case 24: + case 32: + if (maxbps >= 32) + val |= 0x40; + else if (maxbps >= 24) + val |= 0x30; + else + val |= 0x20; + break; + default: + snd_printdd("invalid format width %d\n", snd_pcm_format_width(format)); + return 0; + } + + return val; +} + +/** + * snd_hda_query_supported_pcm - query the supported PCM rates and formats + * @codec: the HDA codec + * @nid: NID to query + * @ratesp: the pointer to store the detected rate bitflags + * @formatsp: the pointer to store the detected formats + * @bpsp: the pointer to store the detected format widths + * + * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp + * or @bsps argument is ignored. + * + * Returns 0 if successful, otherwise a negative error code. + */ +int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, + u32 *ratesp, u64 *formatsp, unsigned int *bpsp) +{ + int i; + unsigned int val, streams; + + val = 0; + if (nid != codec->afg && + snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) { + val = snd_hda_param_read(codec, nid, AC_PAR_PCM); + if (val == -1) + return -EIO; + } + if (! val) + val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); + + if (ratesp) { + u32 rates = 0; + for (i = 0; rate_bits[i][0]; i++) { + if (val & (1 << i)) + rates |= rate_bits[i][1]; + } + *ratesp = rates; + } + + if (formatsp || bpsp) { + u64 formats = 0; + unsigned int bps; + unsigned int wcaps; + + wcaps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); + streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); + if (streams == -1) + return -EIO; + if (! streams) { + streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); + if (streams == -1) + return -EIO; + } + + bps = 0; + if (streams & AC_SUPFMT_PCM) { + if (val & AC_SUPPCM_BITS_8) { + formats |= SNDRV_PCM_FMTBIT_U8; + bps = 8; + } + if (val & AC_SUPPCM_BITS_16) { + formats |= SNDRV_PCM_FMTBIT_S16_LE; + bps = 16; + } + if (wcaps & AC_WCAP_DIGITAL) { + if (val & AC_SUPPCM_BITS_32) + formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; + if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24)) + formats |= SNDRV_PCM_FMTBIT_S32_LE; + if (val & AC_SUPPCM_BITS_24) + bps = 24; + else if (val & AC_SUPPCM_BITS_20) + bps = 20; + } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|AC_SUPPCM_BITS_32)) { + formats |= SNDRV_PCM_FMTBIT_S32_LE; + if (val & AC_SUPPCM_BITS_32) + bps = 32; + else if (val & AC_SUPPCM_BITS_20) + bps = 20; + else if (val & AC_SUPPCM_BITS_24) + bps = 24; + } + } + else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ + formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; + bps = 32; + } else if (streams == AC_SUPFMT_AC3) { /* should be exclusive */ + /* temporary hack: we have still no proper support + * for the direct AC3 stream... + */ + formats |= SNDRV_PCM_FMTBIT_U8; + bps = 8; + } + if (formatsp) + *formatsp = formats; + if (bpsp) + *bpsp = bps; + } + + return 0; +} + +/** + * snd_hda_is_supported_format - check whether the given node supports the format val + * + * Returns 1 if supported, 0 if not. + */ +int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, + unsigned int format) +{ + int i; + unsigned int val = 0, rate, stream; + + if (nid != codec->afg && + snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) { + val = snd_hda_param_read(codec, nid, AC_PAR_PCM); + if (val == -1) + return 0; + } + if (! val) { + val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); + if (val == -1) + return 0; + } + + rate = format & 0xff00; + for (i = 0; rate_bits[i][0]; i++) + if (rate_bits[i][2] == rate) { + if (val & (1 << i)) + break; + return 0; + } + if (! rate_bits[i][0]) + return 0; + + stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); + if (stream == -1) + return 0; + if (! stream && nid != codec->afg) + stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); + if (! stream || stream == -1) + return 0; + + if (stream & AC_SUPFMT_PCM) { + switch (format & 0xf0) { + case 0x00: + if (! (val & AC_SUPPCM_BITS_8)) + return 0; + break; + case 0x10: + if (! (val & AC_SUPPCM_BITS_16)) + return 0; + break; + case 0x20: + if (! (val & AC_SUPPCM_BITS_20)) + return 0; + break; + case 0x30: + if (! (val & AC_SUPPCM_BITS_24)) + return 0; + break; + case 0x40: + if (! (val & AC_SUPPCM_BITS_32)) + return 0; + break; + default: + return 0; + } + } else { + /* FIXME: check for float32 and AC3? */ + } + + return 1; +} + +/* + * PCM stuff + */ +static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + return 0; +} + +static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream) +{ + snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); + return 0; +} + +static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0); + return 0; +} + +static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info) +{ + if (info->nid) { + /* query support PCM information from the given NID */ + if (! info->rates || ! info->formats) + snd_hda_query_supported_pcm(codec, info->nid, + info->rates ? NULL : &info->rates, + info->formats ? NULL : &info->formats, + info->maxbps ? NULL : &info->maxbps); + } + if (info->ops.open == NULL) + info->ops.open = hda_pcm_default_open_close; + if (info->ops.close == NULL) + info->ops.close = hda_pcm_default_open_close; + if (info->ops.prepare == NULL) { + snd_assert(info->nid, return -EINVAL); + info->ops.prepare = hda_pcm_default_prepare; + } + if (info->ops.prepare == NULL) { + snd_assert(info->nid, return -EINVAL); + info->ops.prepare = hda_pcm_default_prepare; + } + if (info->ops.cleanup == NULL) { + snd_assert(info->nid, return -EINVAL); + info->ops.cleanup = hda_pcm_default_cleanup; + } + return 0; +} + +/** + * snd_hda_build_pcms - build PCM information + * @bus: the BUS + * + * Create PCM information for each codec included in the bus. + * + * The build_pcms codec patch is requested to set up codec->num_pcms and + * codec->pcm_info properly. The array is referred by the top-level driver + * to create its PCM instances. + * The allocated codec->pcm_info should be released in codec->patch_ops.free + * callback. + * + * At least, substreams, channels_min and channels_max must be filled for + * each stream. substreams = 0 indicates that the stream doesn't exist. + * When rates and/or formats are zero, the supported values are queried + * from the given nid. The nid is used also by the default ops.prepare + * and ops.cleanup callbacks. + * + * The driver needs to call ops.open in its open callback. Similarly, + * ops.close is supposed to be called in the close callback. + * ops.prepare should be called in the prepare or hw_params callback + * with the proper parameters for set up. + * ops.cleanup should be called in hw_free for clean up of streams. + * + * This function returns 0 if successfull, or a negative error code. + */ +int snd_hda_build_pcms(struct hda_bus *bus) +{ + struct list_head *p; + + list_for_each(p, &bus->codec_list) { + struct hda_codec *codec = list_entry(p, struct hda_codec, list); + unsigned int pcm, s; + int err; + if (! codec->patch_ops.build_pcms) + continue; + err = codec->patch_ops.build_pcms(codec); + if (err < 0) + return err; + for (pcm = 0; pcm < codec->num_pcms; pcm++) { + for (s = 0; s < 2; s++) { + struct hda_pcm_stream *info; + info = &codec->pcm_info[pcm].stream[s]; + if (! info->substreams) + continue; + err = set_pcm_default_values(codec, info); + if (err < 0) + return err; + } + } + } + return 0; +} + + +/** + * snd_hda_check_board_config - compare the current codec with the config table + * @codec: the HDA codec + * @tbl: configuration table, terminated by null entries + * + * Compares the modelname or PCI subsystem id of the current codec with the + * given configuration table. If a matching entry is found, returns its + * config value (supposed to be 0 or positive). + * + * If no entries are matching, the function returns a negative value. + */ +int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl) +{ + struct hda_board_config *c; + + if (codec->bus->modelname) { + for (c = tbl; c->modelname || c->pci_vendor; c++) { + if (c->modelname && + ! strcmp(codec->bus->modelname, c->modelname)) { + snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); + return c->config; + } + } + } + + if (codec->bus->pci) { + u16 subsystem_vendor, subsystem_device; + pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); + pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); + for (c = tbl; c->modelname || c->pci_vendor; c++) { + if (c->pci_vendor == subsystem_vendor && + c->pci_device == subsystem_device) + return c->config; + } + } + return -1; +} + +/** + * snd_hda_add_new_ctls - create controls from the array + * @codec: the HDA codec + * @knew: the array of snd_kcontrol_new_t + * + * This helper function creates and add new controls in the given array. + * The array must be terminated with an empty entry as terminator. + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew) +{ + int err; + + for (; knew->name; knew++) { + err = snd_ctl_add(codec->bus->card, snd_ctl_new1(knew, codec)); + if (err < 0) + return err; + } + return 0; +} + + +/* + * input MUX helper + */ +int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo) +{ + unsigned int index; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = imux->num_items; + index = uinfo->value.enumerated.item; + if (index >= imux->num_items) + index = imux->num_items - 1; + strcpy(uinfo->value.enumerated.name, imux->items[index].label); + return 0; +} + +int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, + snd_ctl_elem_value_t *ucontrol, hda_nid_t nid, + unsigned int *cur_val) +{ + unsigned int idx; + + idx = ucontrol->value.enumerated.item[0]; + if (idx >= imux->num_items) + idx = imux->num_items - 1; + if (*cur_val == idx && ! codec->in_resume) + return 0; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, + imux->items[idx].index); + *cur_val = idx; + return 1; +} + + +/* + * Multi-channel / digital-out PCM helper functions + */ + +/* + * open the digital out in the exclusive mode + */ +int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) +{ + down(&codec->spdif_mutex); + if (mout->dig_out_used) { + up(&codec->spdif_mutex); + return -EBUSY; /* already being used */ + } + mout->dig_out_used = HDA_DIG_EXCLUSIVE; + up(&codec->spdif_mutex); + return 0; +} + +/* + * release the digital out + */ +int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) +{ + down(&codec->spdif_mutex); + mout->dig_out_used = 0; + up(&codec->spdif_mutex); + return 0; +} + +/* + * set up more restrictions for analog out + */ +int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, + snd_pcm_substream_t *substream) +{ + substream->runtime->hw.channels_max = mout->max_channels; + return snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, 2); +} + +/* + * set up the i/o for analog out + * when the digital out is available, copy the front out to digital out, too. + */ +int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream) +{ + hda_nid_t *nids = mout->dac_nids; + int chs = substream->runtime->channels; + int i; + + down(&codec->spdif_mutex); + if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { + if (chs == 2 && + snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && + ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { + mout->dig_out_used = HDA_DIG_ANALOG_DUP; + /* setup digital receiver */ + snd_hda_codec_setup_stream(codec, mout->dig_out_nid, + stream_tag, 0, format); + } else { + mout->dig_out_used = 0; + snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); + } + } + up(&codec->spdif_mutex); + + /* front */ + snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); + if (mout->hp_nid) + /* headphone out will just decode front left/right (stereo) */ + snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); + /* surrounds */ + for (i = 1; i < mout->num_dacs; i++) { + if (i == HDA_REAR && chs == 2) /* copy front to rear */ + snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); + else if (chs >= (i + 1) * 2) /* independent out */ + snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, + format); + } + return 0; +} + +/* + * clean up the setting for analog out + */ +int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout) +{ + hda_nid_t *nids = mout->dac_nids; + int i; + + for (i = 0; i < mout->num_dacs; i++) + snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); + if (mout->hp_nid) + snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); + down(&codec->spdif_mutex); + if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { + snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); + mout->dig_out_used = 0; + } + up(&codec->spdif_mutex); + return 0; +} + +#ifdef CONFIG_PM +/* + * power management + */ + +/** + * snd_hda_suspend - suspend the codecs + * @bus: the HDA bus + * @state: suspsend state + * + * Returns 0 if successful. + */ +int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) +{ + struct list_head *p; + + /* FIXME: should handle power widget capabilities */ + list_for_each(p, &bus->codec_list) { + struct hda_codec *codec = list_entry(p, struct hda_codec, list); + if (codec->patch_ops.suspend) + codec->patch_ops.suspend(codec, state); + } + return 0; +} + +/** + * snd_hda_resume - resume the codecs + * @bus: the HDA bus + * @state: resume state + * + * Returns 0 if successful. + */ +int snd_hda_resume(struct hda_bus *bus) +{ + struct list_head *p; + + list_for_each(p, &bus->codec_list) { + struct hda_codec *codec = list_entry(p, struct hda_codec, list); + if (codec->patch_ops.resume) + codec->patch_ops.resume(codec); + } + return 0; +} + +/** + * snd_hda_resume_ctls - resume controls in the new control list + * @codec: the HDA codec + * @knew: the array of snd_kcontrol_new_t + * + * This function resumes the mixer controls in the snd_kcontrol_new_t array, + * originally for snd_hda_add_new_ctls(). + * The array must be terminated with an empty entry as terminator. + */ +int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew) +{ + snd_ctl_elem_value_t *val; + + val = kmalloc(sizeof(*val), GFP_KERNEL); + if (! val) + return -ENOMEM; + codec->in_resume = 1; + for (; knew->name; knew++) { + int i, count; + count = knew->count ? knew->count : 1; + for (i = 0; i < count; i++) { + memset(val, 0, sizeof(*val)); + val->id.iface = knew->iface; + val->id.device = knew->device; + val->id.subdevice = knew->subdevice; + strcpy(val->id.name, knew->name); + val->id.index = knew->index ? knew->index : i; + /* Assume that get callback reads only from cache, + * not accessing to the real hardware + */ + if (snd_ctl_elem_read(codec->bus->card, val) < 0) + continue; + snd_ctl_elem_write(codec->bus->card, NULL, val); + } + } + codec->in_resume = 0; + kfree(val); + return 0; +} + +/** + * snd_hda_resume_spdif_out - resume the digital out + * @codec: the HDA codec + */ +int snd_hda_resume_spdif_out(struct hda_codec *codec) +{ + return snd_hda_resume_ctls(codec, dig_mixes); +} + +/** + * snd_hda_resume_spdif_in - resume the digital in + * @codec: the HDA codec + */ +int snd_hda_resume_spdif_in(struct hda_codec *codec) +{ + return snd_hda_resume_ctls(codec, dig_in_ctls); +} +#endif + +/* + * symbols exported for controller modules + */ +EXPORT_SYMBOL(snd_hda_codec_read); +EXPORT_SYMBOL(snd_hda_codec_write); +EXPORT_SYMBOL(snd_hda_sequence_write); +EXPORT_SYMBOL(snd_hda_get_sub_nodes); +EXPORT_SYMBOL(snd_hda_queue_unsol_event); +EXPORT_SYMBOL(snd_hda_bus_new); +EXPORT_SYMBOL(snd_hda_codec_new); +EXPORT_SYMBOL(snd_hda_codec_setup_stream); +EXPORT_SYMBOL(snd_hda_calc_stream_format); +EXPORT_SYMBOL(snd_hda_build_pcms); +EXPORT_SYMBOL(snd_hda_build_controls); +#ifdef CONFIG_PM +EXPORT_SYMBOL(snd_hda_suspend); +EXPORT_SYMBOL(snd_hda_resume); +#endif + +/* + * INIT part + */ + +static int __init alsa_hda_init(void) +{ + return 0; +} + +static void __exit alsa_hda_exit(void) +{ +} + +module_init(alsa_hda_init) +module_exit(alsa_hda_exit) diff -Nru a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_codec.h 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,604 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * Copyright (c) 2004 Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SOUND_HDA_CODEC_H +#define __SOUND_HDA_CODEC_H + +#include +#include +#include + +/* + * nodes + */ +#define AC_NODE_ROOT 0x00 + +/* + * function group types + */ +enum { + AC_GRP_AUDIO_FUNCTION = 0x01, + AC_GRP_MODEM_FUNCTION = 0x02, +}; + +/* + * widget types + */ +enum { + AC_WID_AUD_OUT, /* Audio Out */ + AC_WID_AUD_IN, /* Audio In */ + AC_WID_AUD_MIX, /* Audio Mixer */ + AC_WID_AUD_SEL, /* Audio Selector */ + AC_WID_PIN, /* Pin Complex */ + AC_WID_POWER, /* Power */ + AC_WID_VOL_KNB, /* Volume Knob */ + AC_WID_BEEP, /* Beep Generator */ + AC_WID_VENDOR = 0x0f /* Vendor specific */ +}; + +/* + * GET verbs + */ +#define AC_VERB_GET_STREAM_FORMAT 0x0a00 +#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00 +#define AC_VERB_GET_PROC_COEF 0x0c00 +#define AC_VERB_GET_COEF_INDEX 0x0d00 +#define AC_VERB_PARAMETERS 0x0f00 +#define AC_VERB_GET_CONNECT_SEL 0x0f01 +#define AC_VERB_GET_CONNECT_LIST 0x0f02 +#define AC_VERB_GET_PROC_STATE 0x0f03 +#define AC_VERB_GET_SDI_SELECT 0x0f04 +#define AC_VERB_GET_POWER_STATE 0x0f05 +#define AC_VERB_GET_CONV 0x0f06 +#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07 +#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08 +#define AC_VERB_GET_PIN_SENSE 0x0f09 +#define AC_VERB_GET_BEEP_CONTROL 0x0f0a +#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c +#define AC_VERB_GET_DIGI_CONVERT 0x0f0d +#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f +/* f10-f1a: GPIO */ +#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c + +/* + * SET verbs + */ +#define AC_VERB_SET_STREAM_FORMAT 0x200 +#define AC_VERB_SET_AMP_GAIN_MUTE 0x300 +#define AC_VERB_SET_PROC_COEF 0x400 +#define AC_VERB_SET_COEF_INDEX 0x500 +#define AC_VERB_SET_CONNECT_SEL 0x701 +#define AC_VERB_SET_PROC_STATE 0x703 +#define AC_VERB_SET_SDI_SELECT 0x704 +#define AC_VERB_SET_POWER_STATE 0x705 +#define AC_VERB_SET_CHANNEL_STREAMID 0x706 +#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707 +#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708 +#define AC_VERB_SET_PIN_SENSE 0x709 +#define AC_VERB_SET_BEEP_CONTROL 0x70a +#define AC_VERB_SET_EAPD_BTLENALBE 0x70c +#define AC_VERB_SET_DIGI_CONVERT_1 0x70d +#define AC_VERB_SET_DIGI_CONVERT_2 0x70e +#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f +#define AC_VERB_SET_CODEC_RESET 0x7ff + +/* + * Parameter IDs + */ +#define AC_PAR_VENDOR_ID 0x00 +#define AC_PAR_SUBSYSTEM_ID 0x01 +#define AC_PAR_REV_ID 0x02 +#define AC_PAR_NODE_COUNT 0x04 +#define AC_PAR_FUNCTION_TYPE 0x05 +#define AC_PAR_AUDIO_FG_CAP 0x08 +#define AC_PAR_AUDIO_WIDGET_CAP 0x09 +#define AC_PAR_PCM 0x0a +#define AC_PAR_STREAM 0x0b +#define AC_PAR_PIN_CAP 0x0c +#define AC_PAR_AMP_IN_CAP 0x0d +#define AC_PAR_CONNLIST_LEN 0x0e +#define AC_PAR_POWER_STATE 0x0f +#define AC_PAR_PROC_CAP 0x10 +#define AC_PAR_GPIO_CAP 0x11 +#define AC_PAR_AMP_OUT_CAP 0x12 + +/* + * AC_VERB_PARAMETERS results (32bit) + */ + +/* Function Group Type */ +#define AC_FGT_TYPE (0xff<<0) +#define AC_FGT_TYPE_SHIFT 0 +#define AC_FGT_UNSOL_CAP (1<<8) + +/* Audio Function Group Capabilities */ +#define AC_AFG_OUT_DELAY (0xf<<0) +#define AC_AFG_IN_DELAY (0xf<<8) +#define AC_AFG_BEEP_GEN (1<<16) + +/* Audio Widget Capabilities */ +#define AC_WCAP_STEREO (1<<0) /* stereo I/O */ +#define AC_WCAP_IN_AMP (1<<1) /* AMP-in present */ +#define AC_WCAP_OUT_AMP (1<<2) /* AMP-out present */ +#define AC_WCAP_AMP_OVRD (1<<3) /* AMP-parameter override */ +#define AC_WCAP_FORMAT_OVRD (1<<4) /* format override */ +#define AC_WCAP_STRIPE (1<<5) /* stripe */ +#define AC_WCAP_PROC_WID (1<<6) /* Proc Widget */ +#define AC_WCAP_UNSOL_CAP (1<<7) /* Unsol capable */ +#define AC_WCAP_CONN_LIST (1<<8) /* connection list */ +#define AC_WCAP_DIGITAL (1<<9) /* digital I/O */ +#define AC_WCAP_POWER (1<<10) /* power control */ +#define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */ +#define AC_WCAP_DELAY (0xf<<16) +#define AC_WCAP_DELAY_SHIFT 16 +#define AC_WCAP_TYPE (0xf<<20) +#define AC_WCAP_TYPE_SHIFT 20 + +/* supported PCM rates and bits */ +#define AC_SUPPCM_RATES (0xfff << 0) +#define AC_SUPPCM_BITS_8 (1<<16) +#define AC_SUPPCM_BITS_16 (1<<17) +#define AC_SUPPCM_BITS_20 (1<<18) +#define AC_SUPPCM_BITS_24 (1<<19) +#define AC_SUPPCM_BITS_32 (1<<20) + +/* supported PCM stream format */ +#define AC_SUPFMT_PCM (1<<0) +#define AC_SUPFMT_FLOAT32 (1<<1) +#define AC_SUPFMT_AC3 (1<<2) + +/* Pin widget capabilies */ +#define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */ +#define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */ +#define AC_PINCAP_PRES_DETECT (1<<2) /* presence detect capable */ +#define AC_PINCAP_HP_DRV (1<<3) /* headphone drive capable */ +#define AC_PINCAP_OUT (1<<4) /* output capable */ +#define AC_PINCAP_IN (1<<5) /* input capable */ +#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ +#define AC_PINCAP_VREF (7<<8) +#define AC_PINCAP_VREF_SHIFT 8 +#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ +/* Vref status (used in pin cap and pin ctl) */ +#define AC_PIN_VREF_HIZ (1<<0) /* Hi-Z */ +#define AC_PIN_VREF_50 (1<<1) /* 50% */ +#define AC_PIN_VREF_GRD (1<<2) /* ground */ +#define AC_PIN_VREF_80 (1<<4) /* 80% */ +#define AC_PIN_VREF_100 (1<<5) /* 100% */ + + +/* Amplifier capabilities */ +#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ +#define AC_AMPCAP_OFFSET_SHIFT 0 +#define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ +#define AC_AMPCAP_NUM_STEPS_SHIFT 8 +#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB in 0.25dB */ +#define AC_AMPCAP_STEP_SIZE_SHIFT 16 +#define AC_AMPCAP_MUTE (1<<31) /* mute capable */ +#define AC_AMPCAP_MUTE_SHIFT 31 + +/* Connection list */ +#define AC_CLIST_LENGTH (0x7f<<0) +#define AC_CLIST_LONG (1<<7) + +/* Supported power status */ +#define AC_PWRST_D0SUP (1<<0) +#define AC_PWRST_D1SUP (1<<1) +#define AC_PWRST_D2SUP (1<<2) +#define AC_PWRST_D3SUP (1<<3) + +/* Processing capabilies */ +#define AC_PCAP_BENIGN (1<<0) +#define AC_PCAP_NUM_COEF (0xff<<8) + +/* Volume knobs capabilities */ +#define AC_KNBCAP_NUM_STEPS (0x7f<<0) +#define AC_KNBCAP_DELTA (1<<8) + +/* + * Control Parameters + */ + +/* Amp gain/mute */ +#define AC_AMP_MUTE (1<<8) +#define AC_AMP_GAIN (0x7f) +#define AC_AMP_GET_INDEX (0xf<<0) + +#define AC_AMP_GET_LEFT (1<<13) +#define AC_AMP_GET_RIGHT (0<<13) +#define AC_AMP_GET_OUTPUT (1<<15) +#define AC_AMP_GET_INPUT (0<<15) + +#define AC_AMP_SET_INDEX (0xf<<8) +#define AC_AMP_SET_INDEX_SHIFT 8 +#define AC_AMP_SET_RIGHT (1<<12) +#define AC_AMP_SET_LEFT (1<<13) +#define AC_AMP_SET_INPUT (1<<14) +#define AC_AMP_SET_OUTPUT (1<<15) + +/* DIGITAL1 bits */ +#define AC_DIG1_ENABLE (1<<0) +#define AC_DIG1_V (1<<1) +#define AC_DIG1_VCFG (1<<2) +#define AC_DIG1_EMPHASIS (1<<3) +#define AC_DIG1_COPYRIGHT (1<<4) +#define AC_DIG1_NONAUDIO (1<<5) +#define AC_DIG1_PROFESSIONAL (1<<6) +#define AC_DIG1_LEVEL (1<<7) + +/* Pin widget control - 8bit */ +#define AC_PINCTL_VREFEN (0x7<<0) +#define AC_PINCTL_IN_EN (1<<5) +#define AC_PINCTL_OUT_EN (1<<6) +#define AC_PINCTL_HP_EN (1<<7) + +/* configuration default - 32bit */ +#define AC_DEFCFG_SEQUENCE (0xf<<0) +#define AC_DEFCFG_DEF_ASSOC (0xf<<4) +#define AC_DEFCFG_MISC (0xf<<8) +#define AC_DEFCFG_COLOR (0xf<<12) +#define AC_DEFCFG_COLOR_SHIFT 12 +#define AC_DEFCFG_CONN_TYPE (0xf<<16) +#define AC_DEFCFG_CONN_TYPE_SHIFT 16 +#define AC_DEFCFG_DEVICE (0xf<<20) +#define AC_DEFCFG_DEVICE_SHIFT 20 +#define AC_DEFCFG_LOCATION (0x3f<<24) +#define AC_DEFCFG_LOCATION_SHIFT 24 +#define AC_DEFCFG_PORT_CONN (0x3<<30) +#define AC_DEFCFG_PORT_CONN_SHIFT 30 + +/* device device types (0x0-0xf) */ +enum { + AC_JACK_LINE_OUT, + AC_JACK_SPEAKER, + AC_JACK_HP_OUT, + AC_JACK_CD, + AC_JACK_SPDIF_OUT, + AC_JACK_DIG_OTHER_OUT, + AC_JACK_MODEM_LINE_SIDE, + AC_JACK_MODEM_HAND_SIDE, + AC_JACK_LINE_IN, + AC_JACK_AUX, + AC_JACK_MIC_IN, + AC_JACK_TELEPHONY, + AC_JACK_SPDIF_IN, + AC_JACK_DIG_OTHER_IN, + AC_JACK_OTHER = 0xf, +}; + +/* jack connection types (0x0-0xf) */ +enum { + AC_JACK_CONN_UNKNOWN, + AC_JACK_CONN_1_8, + AC_JACK_CONN_1_4, + AC_JACK_CONN_ATAPI, + AC_JACK_CONN_RCA, + AC_JACK_CONN_OPTICAL, + AC_JACK_CONN_OTHER_DIGITAL, + AC_JACK_CONN_OTHER_ANALOG, + AC_JACK_CONN_DIN, + AC_JACK_CONN_XLR, + AC_JACK_CONN_RJ11, + AC_JACK_CONN_COMB, + AC_JACK_CONN_OTHER = 0xf, +}; + +/* jack colors (0x0-0xf) */ +enum { + AC_JACK_COLOR_UNKNOWN, + AC_JACK_COLOR_BLACK, + AC_JACK_COLOR_GREY, + AC_JACK_COLOR_BLUE, + AC_JACK_COLOR_GREEN, + AC_JACK_COLOR_RED, + AC_JACK_COLOR_ORANGE, + AC_JACK_COLOR_YELLOW, + AC_JACK_COLOR_PURPLE, + AC_JACK_COLOR_PINK, + AC_JACK_COLOR_WHITE = 0xe, + AC_JACK_COLOR_OTHER, +}; + +/* Jack location (0x0-0x3f) */ +/* common case */ +enum { + AC_JACK_LOC_NONE, + AC_JACK_LOC_REAR, + AC_JACK_LOC_FRONT, + AC_JACK_LOC_LEFT, + AC_JACK_LOC_RIGHT, + AC_JACK_LOC_TOP, + AC_JACK_LOC_BOTTOM, +}; +/* bits 4-5 */ +enum { + AC_JACK_LOC_EXTERNAL = 0x00, + AC_JACK_LOC_INTERNAL = 0x10, + AC_JACK_LOC_SEPARATE = 0x20, + AC_JACK_LOC_OTHER = 0x30, +}; +enum { + /* external on primary chasis */ + AC_JACK_LOC_REAR_PANEL = 0x07, + AC_JACK_LOC_DRIVE_BAY, + /* internal */ + AC_JACK_LOC_RISER = 0x17, + AC_JACK_LOC_HDMI, + AC_JACK_LOC_ATAPI, + /* others */ + AC_JACK_LOC_MOBILE_IN = 0x37, + AC_JACK_LOC_MOBILE_OUT, +}; + +/* Port connectivity (0-3) */ +enum { + AC_JACK_PORT_COMPLEX, + AC_JACK_PORT_NONE, + AC_JACK_PORT_FIXED, + AC_JACK_PORT_BOTH, +}; + +/* max. connections to a widget */ +#define HDA_MAX_CONNECTIONS 16 + +/* max. codec address */ +#define HDA_MAX_CODEC_ADDRESS 0x0f + +/* + * Structures + */ + +struct hda_bus; +struct hda_codec; +struct hda_pcm; +struct hda_pcm_stream; +struct hda_bus_unsolicited; + +/* NID type */ +typedef u16 hda_nid_t; + +/* bus operators */ +struct hda_bus_ops { + /* send a single command */ + int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm); + /* get a response from the last command */ + unsigned int (*get_response)(struct hda_codec *codec); + /* free the private data */ + void (*private_free)(struct hda_bus *); +}; + +/* template to pass to the bus constructor */ +struct hda_bus_template { + void *private_data; + struct pci_dev *pci; + const char *modelname; + struct hda_bus_ops ops; +}; + +/* + * codec bus + * + * each controller needs to creata a hda_bus to assign the accessor. + * A hda_bus contains several codecs in the list codec_list. + */ +struct hda_bus { + snd_card_t *card; + + /* copied from template */ + void *private_data; + struct pci_dev *pci; + const char *modelname; + struct hda_bus_ops ops; + + /* codec linked list */ + struct list_head codec_list; + struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */ + + struct semaphore cmd_mutex; + + /* unsolicited event queue */ + struct hda_bus_unsolicited *unsol; + + snd_info_entry_t *proc; +}; + +/* + * codec preset + * + * Known codecs have the patch to build and set up the controls/PCMs + * better than the generic parser. + */ +struct hda_codec_preset { + unsigned int id; + unsigned int mask; + unsigned int subs; + unsigned int subs_mask; + unsigned int rev; + const char *name; + int (*patch)(struct hda_codec *codec); +}; + +/* ops set by the preset patch */ +struct hda_codec_ops { + int (*build_controls)(struct hda_codec *codec); + int (*build_pcms)(struct hda_codec *codec); + int (*init)(struct hda_codec *codec); + void (*free)(struct hda_codec *codec); + void (*unsol_event)(struct hda_codec *codec, unsigned int res); +#ifdef CONFIG_PM + int (*suspend)(struct hda_codec *codec, pm_message_t state); + int (*resume)(struct hda_codec *codec); +#endif +}; + +/* record for amp information cache */ +struct hda_amp_info { + u32 key; /* hash key */ + u32 amp_caps; /* amp capabilities */ + u16 vol[2]; /* current volume & mute*/ + u16 status; /* update flag */ + u16 next; /* next link */ +}; + +/* PCM callbacks */ +struct hda_pcm_ops { + int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec, + snd_pcm_substream_t *substream); + int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec, + snd_pcm_substream_t *substream); + int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec, + unsigned int stream_tag, unsigned int format, + snd_pcm_substream_t *substream); + int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec, + snd_pcm_substream_t *substream); +}; + +/* PCM information for each substream */ +struct hda_pcm_stream { + unsigned int substreams; /* number of substreams, 0 = not exist */ + unsigned int channels_min; /* min. number of channels */ + unsigned int channels_max; /* max. number of channels */ + hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ + u32 rates; /* supported rates */ + u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */ + unsigned int maxbps; /* supported max. bit per sample */ + struct hda_pcm_ops ops; +}; + +/* for PCM creation */ +struct hda_pcm { + char *name; + struct hda_pcm_stream stream[2]; +}; + +/* codec information */ +struct hda_codec { + struct hda_bus *bus; + unsigned int addr; /* codec addr*/ + struct list_head list; /* list point */ + + hda_nid_t afg; /* AFG node id */ + + /* ids */ + u32 vendor_id; + u32 subsystem_id; + u32 revision_id; + + /* detected preset */ + const struct hda_codec_preset *preset; + + /* set by patch */ + struct hda_codec_ops patch_ops; + + /* resume phase - all controls should update even if + * the values are not changed + */ + unsigned int in_resume; + + /* PCM to create, set by patch_ops.build_pcms callback */ + unsigned int num_pcms; + struct hda_pcm *pcm_info; + + /* codec specific info */ + void *spec; + + /* hash for amp access */ + u16 amp_hash[32]; + int num_amp_entries; + struct hda_amp_info amp_info[128]; /* big enough? */ + + struct semaphore spdif_mutex; + unsigned int spdif_status; /* IEC958 status bits */ + unsigned short spdif_ctls; /* SPDIF control bits */ + unsigned int spdif_in_enable; /* SPDIF input enable? */ +}; + +/* direction */ +enum { + HDA_INPUT, HDA_OUTPUT +}; + + +/* + * constructors + */ +int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp, + struct hda_bus **busp); +int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, + struct hda_codec **codecp); + +/* + * low level functions + */ +unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm); +int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm); +#define snd_hda_param_read(codec, nid, param) snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) +int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id); +int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); + +struct hda_verb { + hda_nid_t nid; + u32 verb; + u32 param; +}; + +void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq); + +/* unsolicited event */ +int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); + +/* + * Mixer + */ +int snd_hda_build_controls(struct hda_bus *bus); + +/* + * PCM + */ +int snd_hda_build_pcms(struct hda_bus *bus); +void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, + int channel_id, int format); +unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, + unsigned int format, unsigned int maxbps); +int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, + u32 *ratesp, u64 *formatsp, unsigned int *bpsp); +int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, + unsigned int format); + +/* + * Misc + */ +void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); + +/* + * power management + */ +#ifdef CONFIG_PM +int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); +int snd_hda_resume(struct hda_bus *bus); +#endif + +#endif /* __SOUND_HDA_CODEC_H */ diff -Nru a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_generic.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,898 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * Generic widget tree parser + * + * Copyright (c) 2004 Takashi Iwai + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver 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 +#include +#include +#include +#include +#include "hda_codec.h" +#include "hda_local.h" + +/* widget node for parsing */ +struct hda_gnode { + hda_nid_t nid; /* NID of this widget */ + unsigned short nconns; /* number of input connections */ + hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; /* input connections */ + unsigned int wid_caps; /* widget capabilities */ + unsigned char type; /* widget type */ + unsigned char pin_ctl; /* pin controls */ + unsigned char checked; /* the flag indicates that the node is already parsed */ + unsigned int pin_caps; /* pin widget capabilities */ + unsigned int def_cfg; /* default configuration */ + unsigned int amp_out_caps; /* AMP out capabilities */ + unsigned int amp_in_caps; /* AMP in capabilities */ + struct list_head list; +}; + +/* pathc-specific record */ +struct hda_gspec { + struct hda_gnode *dac_node; /* DAC node */ + struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */ + struct hda_gnode *pcm_vol_node; /* Node for PCM volume */ + unsigned int pcm_vol_index; /* connection of PCM volume */ + + struct hda_gnode *adc_node; /* ADC node */ + struct hda_gnode *cap_vol_node; /* Node for capture volume */ + unsigned int cur_cap_src; /* current capture source */ + struct hda_input_mux input_mux; + char cap_labels[HDA_MAX_NUM_INPUTS][16]; + + unsigned int def_amp_in_caps; + unsigned int def_amp_out_caps; + + struct hda_pcm pcm_rec; /* PCM information */ + + struct list_head nid_list; /* list of widgets */ +}; + +/* + * retrieve the default device type from the default config value + */ +#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) +#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) + +/* + * destructor + */ +static void snd_hda_generic_free(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + struct list_head *p, *n; + + if (! spec) + return; + /* free all widgets */ + list_for_each_safe(p, n, &spec->nid_list) { + struct hda_gnode *node = list_entry(p, struct hda_gnode, list); + kfree(node); + } + kfree(spec); +} + + +/* + * add a new widget node and read its attributes + */ +static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid_t nid) +{ + struct hda_gnode *node; + int nconns; + + node = kcalloc(1, sizeof(*node), GFP_KERNEL); + if (node == NULL) + return -ENOMEM; + node->nid = nid; + nconns = snd_hda_get_connections(codec, nid, node->conn_list, HDA_MAX_CONNECTIONS); + if (nconns < 0) { + kfree(node); + return nconns; + } + node->nconns = nconns; + node->wid_caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); + node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + + if (node->type == AC_WID_PIN) { + node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP); + node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); + } + + if (node->wid_caps & AC_WCAP_OUT_AMP) { + if (node->wid_caps & AC_WCAP_AMP_OVRD) + node->amp_out_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_OUT_CAP); + if (! node->amp_out_caps) + node->amp_out_caps = spec->def_amp_out_caps; + } + if (node->wid_caps & AC_WCAP_IN_AMP) { + if (node->wid_caps & AC_WCAP_AMP_OVRD) + node->amp_in_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_IN_CAP); + if (! node->amp_in_caps) + node->amp_in_caps = spec->def_amp_in_caps; + } + list_add_tail(&node->list, &spec->nid_list); + return 0; +} + +/* + * build the AFG subtree + */ +static int build_afg_tree(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + int i, nodes, err; + hda_nid_t nid; + + snd_assert(spec, return -EINVAL); + + spec->def_amp_out_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_OUT_CAP); + spec->def_amp_in_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_IN_CAP); + + nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); + if (! nid || nodes < 0) { + printk(KERN_ERR "Invalid AFG subtree\n"); + return -EINVAL; + } + + /* parse all nodes belonging to the AFG */ + for (i = 0; i < nodes; i++, nid++) { + if ((err = add_new_node(codec, spec, nid)) < 0) + return err; + } + + return 0; +} + + +/* + * look for the node record for the given NID + */ +/* FIXME: should avoid the braindead linear search */ +static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid) +{ + struct list_head *p; + struct hda_gnode *node; + + list_for_each(p, &spec->nid_list) { + node = list_entry(p, struct hda_gnode, list); + if (node->nid == nid) + return node; + } + return NULL; +} + +/* + * unmute (and set max vol) the output amplifier + */ +static int unmute_output(struct hda_codec *codec, struct hda_gnode *node) +{ + unsigned int val, ofs; + snd_printdd("UNMUTE OUT: NID=0x%x\n", node->nid); + val = (node->amp_out_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; + ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; + if (val >= ofs) + val -= ofs; + val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT; + val |= AC_AMP_SET_OUTPUT; + return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); +} + +/* + * unmute (and set max vol) the input amplifier + */ +static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigned int index) +{ + unsigned int val, ofs; + snd_printdd("UNMUTE IN: NID=0x%x IDX=0x%x\n", node->nid, index); + val = (node->amp_in_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; + ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; + if (val >= ofs) + val -= ofs; + val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT; + val |= AC_AMP_SET_INPUT; + // awk added - fixed to allow unmuting of indexed amps + val |= index << AC_AMP_SET_INDEX_SHIFT; + return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); +} + +/* + * select the input connection of the given node. + */ +static int select_input_connection(struct hda_codec *codec, struct hda_gnode *node, + unsigned int index) +{ + snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index); + return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_CONNECT_SEL, index); +} + +/* + * clear checked flag of each node in the node list + */ +static void clear_check_flags(struct hda_gspec *spec) +{ + struct list_head *p; + struct hda_gnode *node; + + list_for_each(p, &spec->nid_list) { + node = list_entry(p, struct hda_gnode, list); + node->checked = 0; + } +} + +/* + * parse the output path recursively until reach to an audio output widget + * + * returns 0 if not found, 1 if found, or a negative error code. + */ +static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, + struct hda_gnode *node) +{ + int i, err; + struct hda_gnode *child; + + if (node->checked) + return 0; + + node->checked = 1; + if (node->type == AC_WID_AUD_OUT) { + snd_printdd("AUD_OUT found %x\n", node->nid); + if (spec->dac_node) { + /* already DAC node is assigned, just unmute & connect */ + return node == spec->dac_node; + } + spec->dac_node = node; + if (node->wid_caps & AC_WCAP_OUT_AMP) { + spec->pcm_vol_node = node; + spec->pcm_vol_index = 0; + } + return 1; /* found */ + } + + for (i = 0; i < node->nconns; i++) { + child = hda_get_node(spec, node->conn_list[i]); + if (! child) + continue; + err = parse_output_path(codec, spec, child); + if (err < 0) + return err; + else if (err > 0) { + /* found one, + * select the path, unmute both input and output + */ + if (node->nconns > 1) + select_input_connection(codec, node, i); + unmute_input(codec, node, i); + unmute_output(codec, node); + if (! spec->pcm_vol_node) { + if (node->wid_caps & AC_WCAP_IN_AMP) { + spec->pcm_vol_node = node; + spec->pcm_vol_index = i; + } else if (node->wid_caps & AC_WCAP_OUT_AMP) { + spec->pcm_vol_node = node; + spec->pcm_vol_index = 0; + } + } + return 1; + } + } + return 0; +} + +/* + * Look for the output PIN widget with the given jack type + * and parse the output path to that PIN. + * + * Returns the PIN node when the path to DAC is established. + */ +static struct hda_gnode *parse_output_jack(struct hda_codec *codec, + struct hda_gspec *spec, + int jack_type) +{ + struct list_head *p; + struct hda_gnode *node; + int err; + + list_for_each(p, &spec->nid_list) { + node = list_entry(p, struct hda_gnode, list); + if (node->type != AC_WID_PIN) + continue; + /* output capable? */ + if (! (node->pin_caps & AC_PINCAP_OUT)) + continue; + if (jack_type >= 0) { + if (jack_type != get_defcfg_type(node)) + continue; + } else { + /* output as default? */ + if (! (node->pin_ctl & AC_PINCTL_OUT_EN)) + continue; + } + clear_check_flags(spec); + err = parse_output_path(codec, spec, node); + if (err < 0) + return NULL; + else if (err > 0) { + /* unmute the PIN output */ + unmute_output(codec, node); + /* set PIN-Out enable */ + snd_hda_codec_write(codec, node->nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); + return node; + } + } + return NULL; +} + + +/* + * parse outputs + */ +static int parse_output(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + struct hda_gnode *node; + + /* + * Look for the output PIN widget + */ + /* first, look for the line-out pin */ + node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT); + if (node) /* found, remember the PIN node */ + spec->out_pin_node = node; + /* look for the HP-out pin */ + node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); + if (node) { + if (! spec->out_pin_node) + spec->out_pin_node = node; + } + + if (! spec->out_pin_node) { + /* no line-out or HP pins found, + * then choose for the first output pin + */ + spec->out_pin_node = parse_output_jack(codec, spec, -1); + if (! spec->out_pin_node) + snd_printd("hda_generic: no proper output path found\n"); + } + + return 0; +} + +/* + * input MUX + */ + +/* control callbacks */ +static int capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_gspec *spec = codec->spec; + return snd_hda_input_mux_info(&spec->input_mux, uinfo); +} + +static int capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_gspec *spec = codec->spec; + + ucontrol->value.enumerated.item[0] = spec->cur_cap_src; + return 0; +} + +static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_gspec *spec = codec->spec; + return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol, + spec->adc_node->nid, &spec->cur_cap_src); +} + +/* + * return the string name of the given input PIN widget + */ +static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) +{ + unsigned int location = get_defcfg_location(node); + switch (get_defcfg_type(node)) { + case AC_JACK_LINE_IN: + if ((location & 0x0f) == AC_JACK_LOC_FRONT) + return "Front Line"; + return "Line"; + case AC_JACK_CD: + if (pinctl) + *pinctl |= AC_PIN_VREF_GRD; + return "CD"; + case AC_JACK_AUX: + if ((location & 0x0f) == AC_JACK_LOC_FRONT) + return "Front Aux"; + return "Aux"; + case AC_JACK_MIC_IN: + if ((location & 0x0f) == AC_JACK_LOC_FRONT) + return "Front Mic"; + return "Mic"; + case AC_JACK_SPDIF_IN: + return "SPDIF"; + case AC_JACK_DIG_OTHER_IN: + return "Digital"; + } + return NULL; +} + +/* + * parse the nodes recursively until reach to the input PIN + * + * returns 0 if not found, 1 if found, or a negative error code. + */ +static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, + struct hda_gnode *node) +{ + int i, err; + unsigned int pinctl; + char *label; + const char *type; + + if (node->checked) + return 0; + + node->checked = 1; + if (node->type != AC_WID_PIN) { + for (i = 0; i < node->nconns; i++) { + struct hda_gnode *child; + child = hda_get_node(spec, node->conn_list[i]); + if (! child) + continue; + err = parse_adc_sub_nodes(codec, spec, child); + if (err < 0) + return err; + if (err > 0) { + /* found one, + * select the path, unmute both input and output + */ + if (node->nconns > 1) + select_input_connection(codec, node, i); + unmute_input(codec, node, i); + unmute_output(codec, node); + return err; + } + } + return 0; + } + + /* input capable? */ + if (! (node->pin_caps & AC_PINCAP_IN)) + return 0; + + if (spec->input_mux.num_items >= HDA_MAX_NUM_INPUTS) { + snd_printk(KERN_ERR "hda_generic: Too many items for capture\n"); + return -EINVAL; + } + + pinctl = AC_PINCTL_IN_EN; + /* create a proper capture source label */ + type = get_input_type(node, &pinctl); + if (! type) { + /* input as default? */ + if (! (node->pin_ctl & AC_PINCTL_IN_EN)) + return 0; + type = "Input"; + } + label = spec->cap_labels[spec->input_mux.num_items]; + strcpy(label, type); + spec->input_mux.items[spec->input_mux.num_items].label = label; + + /* unmute the PIN external input */ + unmute_input(codec, node, 0); /* index = 0? */ + /* set PIN-In enable */ + snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); + + return 1; /* found */ +} + +/* + * parse input + */ +static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) +{ + struct hda_gspec *spec = codec->spec; + struct hda_gnode *node; + int i, err; + + snd_printdd("AUD_IN = %x\n", adc_node->nid); + clear_check_flags(spec); + + // awk added - fixed no recording due to muted widget + unmute_input(codec, adc_node, 0); + + /* + * check each connection of the ADC + * if it reaches to a proper input PIN, add the path as the + * input path. + */ + for (i = 0; i < adc_node->nconns; i++) { + node = hda_get_node(spec, adc_node->conn_list[i]); + if (! node) + continue; + err = parse_adc_sub_nodes(codec, spec, node); + if (err < 0) + return err; + else if (err > 0) { + struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items]; + char *buf = spec->cap_labels[spec->input_mux.num_items]; + int ocap; + for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) { + if (! strcmp(buf, spec->cap_labels[ocap])) { + /* same label already exists, + * put the index number to be unique + */ + sprintf(buf, "%s %d", spec->cap_labels[ocap], + spec->input_mux.num_items); + } + } + csrc->index = i; + spec->input_mux.num_items++; + } + } + + if (! spec->input_mux.num_items) + return 0; /* no input path found... */ + + snd_printdd("[Capture Source] NID=0x%x, #SRC=%d\n", adc_node->nid, spec->input_mux.num_items); + for (i = 0; i < spec->input_mux.num_items; i++) + snd_printdd(" [%s] IDX=0x%x\n", spec->input_mux.items[i].label, + spec->input_mux.items[i].index); + + spec->adc_node = adc_node; + return 1; +} + +/* + * parse input + */ +static int parse_input(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + struct list_head *p; + struct hda_gnode *node; + int err; + + /* + * At first we look for an audio input widget. + * If it reaches to certain input PINs, we take it as the + * input path. + */ + list_for_each(p, &spec->nid_list) { + node = list_entry(p, struct hda_gnode, list); + if (node->type == AC_WID_AUD_IN) { + err = parse_input_path(codec, node); + if (err < 0) + return err; + else if (err > 0) + return 0; + } + } + snd_printd("hda_generic: no proper input path found\n"); + return 0; +} + +/* + * create mixer controls if possible + */ +#define DIR_OUT 0x1 +#define DIR_IN 0x2 + +static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, + unsigned int index, const char *type, const char *dir_sfx) +{ + char name[32]; + int err; + int created = 0; + + if (type) + sprintf(name, "%s %s Switch", type, dir_sfx); + else + sprintf(name, "%s Switch", dir_sfx); + if ((node->wid_caps & AC_WCAP_IN_AMP) && + (node->amp_in_caps & AC_AMPCAP_MUTE)) { + snd_kcontrol_new_t knew = + HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); + snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); + if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) + return err; + created = 1; + } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && + (node->amp_out_caps & AC_AMPCAP_MUTE)) { + snd_kcontrol_new_t knew = + HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); + snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); + if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) + return err; + created = 1; + } + + if (type) + sprintf(name, "%s %s Volume", type, dir_sfx); + else + sprintf(name, "%s Volume", dir_sfx); + if ((node->wid_caps & AC_WCAP_IN_AMP) && + (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { + snd_kcontrol_new_t knew = + HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); + snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); + if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) + return err; + created = 1; + } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && + (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { + snd_kcontrol_new_t knew = + HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); + snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); + if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) + return err; + created = 1; + } + + return created; +} + +/* + * check whether the controls with the given name and direction suffix already exist + */ +static int check_existing_control(struct hda_codec *codec, const char *type, const char *dir) +{ + snd_ctl_elem_id_t id; + memset(&id, 0, sizeof(id)); + sprintf(id.name, "%s %s Volume", type, dir); + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + if (snd_ctl_find_id(codec->bus->card, &id)) + return 1; + sprintf(id.name, "%s %s Switch", type, dir); + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + if (snd_ctl_find_id(codec->bus->card, &id)) + return 1; + return 0; +} + +/* + * build output mixer controls + */ +static int build_output_controls(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + int err; + + err = create_mixer(codec, spec->pcm_vol_node, spec->pcm_vol_index, + "PCM", "Playback"); + if (err < 0) + return err; + return 0; +} + +/* create capture volume/switch */ +static int build_input_controls(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + struct hda_gnode *adc_node = spec->adc_node; + int err; + + if (! adc_node) + return 0; /* not found */ + + /* create capture volume and switch controls if the ADC has an amp */ + err = create_mixer(codec, adc_node, 0, NULL, "Capture"); + + /* create input MUX if multiple sources are available */ + if (spec->input_mux.num_items > 1) { + static snd_kcontrol_new_t cap_sel = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = capture_source_info, + .get = capture_source_get, + .put = capture_source_put, + }; + if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0) + return err; + spec->cur_cap_src = 0; + select_input_connection(codec, adc_node, spec->input_mux.items[0].index); + } + return 0; +} + + +/* + * parse the nodes recursively until reach to the output PIN. + * + * returns 0 - if not found, + * 1 - if found, but no mixer is created + * 2 - if found and mixer was already created, (just skip) + * a negative error code + */ +static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, + struct hda_gnode *node, struct hda_gnode *dest_node, + const char *type) +{ + int i, err; + + if (node->checked) + return 0; + + node->checked = 1; + if (node == dest_node) { + /* loopback connection found */ + return 1; + } + + for (i = 0; i < node->nconns; i++) { + struct hda_gnode *child = hda_get_node(spec, node->conn_list[i]); + if (! child) + continue; + err = parse_loopback_path(codec, spec, child, dest_node, type); + if (err < 0) + return err; + else if (err >= 1) { + if (err == 1) { + err = create_mixer(codec, node, i, type, "Playback"); + if (err < 0) + return err; + if (err > 0) + return 2; /* ok, created */ + /* not created, maybe in the lower path */ + err = 1; + } + /* connect and unmute */ + if (node->nconns > 1) + select_input_connection(codec, node, i); + unmute_input(codec, node, i); + unmute_output(codec, node); + return err; + } + } + return 0; +} + +/* + * parse the tree and build the loopback controls + */ +static int build_loopback_controls(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + struct list_head *p; + struct hda_gnode *node; + int err; + const char *type; + + if (! spec->out_pin_node) + return 0; + + list_for_each(p, &spec->nid_list) { + node = list_entry(p, struct hda_gnode, list); + if (node->type != AC_WID_PIN) + continue; + /* input capable? */ + if (! (node->pin_caps & AC_PINCAP_IN)) + return 0; + type = get_input_type(node, NULL); + if (type) { + if (check_existing_control(codec, type, "Playback")) + continue; + clear_check_flags(spec); + err = parse_loopback_path(codec, spec, spec->out_pin_node, + node, type); + if (err < 0) + return err; + if (! err) + continue; + } + } + return 0; +} + +/* + * build mixer controls + */ +static int build_generic_controls(struct hda_codec *codec) +{ + int err; + + if ((err = build_input_controls(codec)) < 0 || + (err = build_output_controls(codec)) < 0 || + (err = build_loopback_controls(codec)) < 0) + return err; + + return 0; +} + +/* + * PCM + */ +static struct hda_pcm_stream generic_pcm_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, +}; + +static int build_generic_pcms(struct hda_codec *codec) +{ + struct hda_gspec *spec = codec->spec; + struct hda_pcm *info = &spec->pcm_rec; + + if (! spec->dac_node && ! spec->adc_node) { + snd_printd("hda_generic: no PCM found\n"); + return 0; + } + + codec->num_pcms = 1; + codec->pcm_info = info; + + info->name = "HDA Generic"; + if (spec->dac_node) { + info->stream[0] = generic_pcm_playback; + info->stream[0].nid = spec->dac_node->nid; + } + if (spec->adc_node) { + info->stream[1] = generic_pcm_playback; + info->stream[1].nid = spec->adc_node->nid; + } + + return 0; +} + + +/* + */ +static struct hda_codec_ops generic_patch_ops = { + .build_controls = build_generic_controls, + .build_pcms = build_generic_pcms, + .free = snd_hda_generic_free, +}; + +/* + * the generic parser + */ +int snd_hda_parse_generic_codec(struct hda_codec *codec) +{ + struct hda_gspec *spec; + int err; + + spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + if (spec == NULL) { + printk(KERN_ERR "hda_generic: can't allocate spec\n"); + return -ENOMEM; + } + codec->spec = spec; + INIT_LIST_HEAD(&spec->nid_list); + + if ((err = build_afg_tree(codec)) < 0) + goto error; + + if ((err = parse_input(codec)) < 0 || + (err = parse_output(codec)) < 0) + goto error; + + codec->patch_ops = generic_patch_ops; + + return 0; + + error: + snd_hda_generic_free(codec); + return err; +} diff -Nru a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_intel.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,1449 @@ +/* + * + * hda_intel.c - Implementation of primary alsa driver code base for Intel HD Audio. + * + * Copyright(c) 2004 Intel Corporation. All rights reserved. + * + * Copyright (c) 2004 Takashi Iwai + * PeiSen Hou + * + * 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. + * + * CONTACTS: + * + * Matt Jared matt.jared@intel.com + * Andy Kopp andy.kopp@intel.com + * Dan Kogan dan.d.kogan@intel.com + * + * CHANGES: + * + * 2004.12.01 Major rewrite by tiwai, merged the work of pshou + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hda_codec.h" + + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static char *model[SNDRV_CARDS]; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for Intel HD audio interface."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); +module_param_array(model, charp, NULL, 0444); +MODULE_PARM_DESC(model, "Use the given board model."); + +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," + "{Intel, ICH6M}," + "{Intel, ICH7}}"); +MODULE_DESCRIPTION("Intel HDA driver"); + +#define SFX "hda-intel: " + +/* + * registers + */ +#define ICH6_REG_GCAP 0x00 +#define ICH6_REG_VMIN 0x02 +#define ICH6_REG_VMAJ 0x03 +#define ICH6_REG_OUTPAY 0x04 +#define ICH6_REG_INPAY 0x06 +#define ICH6_REG_GCTL 0x08 +#define ICH6_REG_WAKEEN 0x0c +#define ICH6_REG_STATESTS 0x0e +#define ICH6_REG_GSTS 0x10 +#define ICH6_REG_INTCTL 0x20 +#define ICH6_REG_INTSTS 0x24 +#define ICH6_REG_WALCLK 0x30 +#define ICH6_REG_SYNC 0x34 +#define ICH6_REG_CORBLBASE 0x40 +#define ICH6_REG_CORBUBASE 0x44 +#define ICH6_REG_CORBWP 0x48 +#define ICH6_REG_CORBRP 0x4A +#define ICH6_REG_CORBCTL 0x4c +#define ICH6_REG_CORBSTS 0x4d +#define ICH6_REG_CORBSIZE 0x4e + +#define ICH6_REG_RIRBLBASE 0x50 +#define ICH6_REG_RIRBUBASE 0x54 +#define ICH6_REG_RIRBWP 0x58 +#define ICH6_REG_RINTCNT 0x5a +#define ICH6_REG_RIRBCTL 0x5c +#define ICH6_REG_RIRBSTS 0x5d +#define ICH6_REG_RIRBSIZE 0x5e + +#define ICH6_REG_IC 0x60 +#define ICH6_REG_IR 0x64 +#define ICH6_REG_IRS 0x68 +#define ICH6_IRS_VALID (1<<1) +#define ICH6_IRS_BUSY (1<<0) + +#define ICH6_REG_DPLBASE 0x70 +#define ICH6_REG_DPUBASE 0x74 +#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ + +/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ +enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; + +/* stream register offsets from stream base */ +#define ICH6_REG_SD_CTL 0x00 +#define ICH6_REG_SD_STS 0x03 +#define ICH6_REG_SD_LPIB 0x04 +#define ICH6_REG_SD_CBL 0x08 +#define ICH6_REG_SD_LVI 0x0c +#define ICH6_REG_SD_FIFOW 0x0e +#define ICH6_REG_SD_FIFOSIZE 0x10 +#define ICH6_REG_SD_FORMAT 0x12 +#define ICH6_REG_SD_BDLPL 0x18 +#define ICH6_REG_SD_BDLPU 0x1c + +/* PCI space */ +#define ICH6_PCIREG_TCSEL 0x44 + +/* + * other constants + */ + +/* max number of SDs */ +#define MAX_ICH6_DEV 8 +/* max number of fragments - we may use more if allocating more pages for BDL */ +#define AZX_MAX_FRAG (PAGE_SIZE / (MAX_ICH6_DEV * 16)) +/* max buffer size - no h/w limit, you can increase as you like */ +#define AZX_MAX_BUF_SIZE (1024*1024*1024) +/* max number of PCM devics per card */ +#define AZX_MAX_PCMS 8 + +/* RIRB int mask: overrun[2], response[0] */ +#define RIRB_INT_RESPONSE 0x01 +#define RIRB_INT_OVERRUN 0x04 +#define RIRB_INT_MASK 0x05 + +/* STATESTS int mask: SD2,SD1,SD0 */ +#define STATESTS_INT_MASK 0x07 +#define AZX_MAX_CODECS 3 + +/* SD_CTL bits */ +#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ +#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ +#define SD_CTL_STREAM_TAG_MASK (0xf << 20) +#define SD_CTL_STREAM_TAG_SHIFT 20 + +/* SD_CTL and SD_STS */ +#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ +#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ +#define SD_INT_COMPLETE 0x04 /* completion interrupt */ +#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|SD_INT_COMPLETE) + +/* SD_STS */ +#define SD_STS_FIFO_READY 0x20 /* FIFO ready */ + +/* INTCTL and INTSTS */ +#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ +#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ +#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ + +/* GCTL reset bit */ +#define ICH6_GCTL_RESET (1<<0) + +/* CORB/RIRB control, read/write pointer */ +#define ICH6_RBCTL_DMA_EN 0x02 /* enable DMA */ +#define ICH6_RBCTL_IRQ_EN 0x01 /* enable IRQ */ +#define ICH6_RBRWP_CLR 0x8000 /* read/write pointer clear */ +/* below are so far hardcoded - should read registers in future */ +#define ICH6_MAX_CORB_ENTRIES 256 +#define ICH6_MAX_RIRB_ENTRIES 256 + + +/* + * Use CORB/RIRB for communication from/to codecs. + * This is the way recommended by Intel (see below). + */ +#define USE_CORB_RIRB + +/* + * Define this if use the position buffer instead of reading SD_LPIB + * It's not used as default since SD_LPIB seems to give more accurate position + */ +/* #define USE_POSBUF */ + +/* + */ + +typedef struct snd_azx azx_t; +typedef struct snd_azx_rb azx_rb_t; +typedef struct snd_azx_dev azx_dev_t; + +struct snd_azx_dev { + u32 *bdl; /* virtual address of the BDL */ + dma_addr_t bdl_addr; /* physical address of the BDL */ + volatile u32 *posbuf; /* position buffer pointer */ + + unsigned int bufsize; /* size of the play buffer in bytes */ + unsigned int fragsize; /* size of each period in bytes */ + unsigned int frags; /* number for period in the play buffer */ + unsigned int fifo_size; /* FIFO size */ + + void __iomem *sd_addr; /* stream descriptor pointer */ + + u32 sd_int_sta_mask; /* stream int status mask */ + + /* pcm support */ + snd_pcm_substream_t *substream; /* assigned substream, set in PCM open */ + unsigned int format_val; /* format value to be set in the controller and the codec */ + unsigned char stream_tag; /* assigned stream */ + unsigned char index; /* stream index */ + + unsigned int opened: 1; + unsigned int running: 1; +}; + +/* CORB/RIRB */ +struct snd_azx_rb { + u32 *buf; /* CORB/RIRB buffer + * Each CORB entry is 4byte, RIRB is 8byte + */ + dma_addr_t addr; /* physical address of CORB/RIRB buffer */ + /* for RIRB */ + unsigned short rp, wp; /* read/write pointers */ + int cmds; /* number of pending requests */ + u32 res; /* last read value */ +}; + +struct snd_azx { + snd_card_t *card; + struct pci_dev *pci; + + /* pci resources */ + unsigned long addr; + void __iomem *remap_addr; + int irq; + + /* locks */ + spinlock_t reg_lock; + struct semaphore open_mutex; + + /* streams */ + azx_dev_t azx_dev[MAX_ICH6_DEV]; + + /* PCM */ + unsigned int pcm_devs; + snd_pcm_t *pcm[AZX_MAX_PCMS]; + + /* HD codec */ + unsigned short codec_mask; + struct hda_bus *bus; + + /* CORB/RIRB */ + azx_rb_t corb; + azx_rb_t rirb; + + /* BDL, CORB/RIRB and position buffers */ + struct snd_dma_buffer bdl; + struct snd_dma_buffer rb; + struct snd_dma_buffer posbuf; +}; + +/* + * macros for easy use + */ +#define azx_writel(chip,reg,value) \ + writel(value, (chip)->remap_addr + ICH6_REG_##reg) +#define azx_readl(chip,reg) \ + readl((chip)->remap_addr + ICH6_REG_##reg) +#define azx_writew(chip,reg,value) \ + writew(value, (chip)->remap_addr + ICH6_REG_##reg) +#define azx_readw(chip,reg) \ + readw((chip)->remap_addr + ICH6_REG_##reg) +#define azx_writeb(chip,reg,value) \ + writeb(value, (chip)->remap_addr + ICH6_REG_##reg) +#define azx_readb(chip,reg) \ + readb((chip)->remap_addr + ICH6_REG_##reg) + +#define azx_sd_writel(dev,reg,value) \ + writel(value, (dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_readl(dev,reg) \ + readl((dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_writew(dev,reg,value) \ + writew(value, (dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_readw(dev,reg) \ + readw((dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_writeb(dev,reg,value) \ + writeb(value, (dev)->sd_addr + ICH6_REG_##reg) +#define azx_sd_readb(dev,reg) \ + readb((dev)->sd_addr + ICH6_REG_##reg) + +/* for pcm support */ +#define get_azx_dev(substream) (azx_dev_t*)(substream->runtime->private_data) + +/* Get the upper 32bit of the given dma_addr_t + * Compiler should optimize and eliminate the code if dma_addr_t is 32bit + */ +#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0) + + +/* + * Interface for HD codec + */ + +#ifdef USE_CORB_RIRB +/* + * CORB / RIRB interface + */ +static int azx_alloc_cmd_io(azx_t *chip) +{ + int err; + + /* single page (at least 4096 bytes) must suffice for both ringbuffes */ + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), + PAGE_SIZE, &chip->rb); + if (err < 0) { + snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n"); + return err; + } + return 0; +} + +static void azx_init_cmd_io(azx_t *chip) +{ + /* CORB set up */ + chip->corb.addr = chip->rb.addr; + chip->corb.buf = (u32 *)chip->rb.area; + azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); + azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr)); + + /* set the corb write pointer to 0 */ + azx_writew(chip, CORBWP, 0); + /* reset the corb hw read pointer */ + azx_writew(chip, CORBRP, ICH6_RBRWP_CLR); + /* enable corb dma */ + azx_writeb(chip, CORBCTL, ICH6_RBCTL_DMA_EN); + + /* RIRB set up */ + chip->rirb.addr = chip->rb.addr + 2048; + chip->rirb.buf = (u32 *)(chip->rb.area + 2048); + azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); + azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr)); + + /* reset the rirb hw write pointer */ + azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR); + /* set N=1, get RIRB response interrupt for new entry */ + azx_writew(chip, RINTCNT, 1); + /* enable rirb dma and response irq */ +#ifdef USE_CORB_RIRB + azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); +#else + azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN); +#endif + chip->rirb.rp = chip->rirb.cmds = 0; +} + +static void azx_free_cmd_io(azx_t *chip) +{ + /* disable ringbuffer DMAs */ + azx_writeb(chip, RIRBCTL, 0); + azx_writeb(chip, CORBCTL, 0); +} + +/* send a command */ +static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int para) +{ + azx_t *chip = codec->bus->private_data; + unsigned int wp; + u32 val; + + val = (u32)(codec->addr & 0x0f) << 28; + val |= (u32)direct << 27; + val |= (u32)nid << 20; + val |= verb << 8; + val |= para; + + /* add command to corb */ + wp = azx_readb(chip, CORBWP); + wp++; + wp %= ICH6_MAX_CORB_ENTRIES; + + spin_lock_irq(&chip->reg_lock); + chip->rirb.cmds++; + chip->corb.buf[wp] = cpu_to_le32(val); + azx_writel(chip, CORBWP, wp); + spin_unlock_irq(&chip->reg_lock); + + return 0; +} + +#define ICH6_RIRB_EX_UNSOL_EV (1<<4) + +/* retrieve RIRB entry - called from interrupt handler */ +static void azx_update_rirb(azx_t *chip) +{ + unsigned int rp, wp; + u32 res, res_ex; + + wp = azx_readb(chip, RIRBWP); + if (wp == chip->rirb.wp) + return; + chip->rirb.wp = wp; + + while (chip->rirb.rp != wp) { + chip->rirb.rp++; + chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; + + rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ + res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); + res = le32_to_cpu(chip->rirb.buf[rp]); + if (res_ex & ICH6_RIRB_EX_UNSOL_EV) + snd_hda_queue_unsol_event(chip->bus, res, res_ex); + else if (chip->rirb.cmds) { + chip->rirb.cmds--; + chip->rirb.res = res; + } + } +} + +/* receive a response */ +static unsigned int azx_get_response(struct hda_codec *codec) +{ + azx_t *chip = codec->bus->private_data; + int timeout = 50; + + while (chip->rirb.cmds) { + if (! --timeout) { + snd_printk(KERN_ERR "azx_get_response timeout\n"); + chip->rirb.rp = azx_readb(chip, RIRBWP); + chip->rirb.cmds = 0; + return -1; + } + msleep(1); + } + return chip->rirb.res; /* the last value */ +} + +#else +/* + * Use the single immediate command instead of CORB/RIRB for simplicity + * + * Note: according to Intel, this is not preferred use. The command was + * intended for the BIOS only, and may get confused with unsolicited + * responses. So, we shouldn't use it for normal operation from the + * driver. + * I left the codes, however, for debugging/testing purposes. + */ + +#define azx_alloc_cmd_io(chip) 0 +#define azx_init_cmd_io(chip) +#define azx_free_cmd_io(chip) + +/* send a command */ +static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int para) +{ + azx_t *chip = codec->bus->private_data; + u32 val; + int timeout = 50; + + val = (u32)(codec->addr & 0x0f) << 28; + val |= (u32)direct << 27; + val |= (u32)nid << 20; + val |= verb << 8; + val |= para; + + while (timeout--) { + /* check ICB busy bit */ + if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) { + /* Clear IRV valid bit */ + azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_VALID); + azx_writel(chip, IC, val); + azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY); + return 0; + } + udelay(1); + } + snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", azx_readw(chip, IRS), val); + return -EIO; +} + +/* receive a response */ +static unsigned int azx_get_response(struct hda_codec *codec) +{ + azx_t *chip = codec->bus->private_data; + int timeout = 50; + + while (timeout--) { + /* check IRV busy bit */ + if (azx_readw(chip, IRS) & ICH6_IRS_VALID) + return azx_readl(chip, IR); + udelay(1); + } + snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS)); + return (unsigned int)-1; +} + +#define azx_update_rirb(chip) + +#endif /* USE_CORB_RIRB */ + +/* reset codec link */ +static int azx_reset(azx_t *chip) +{ + int count; + + /* reset controller */ + azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); + + count = 50; + while (azx_readb(chip, GCTL) && --count) + msleep(1); + + /* delay for >= 100us for codec PLL to settle per spec + * Rev 0.9 section 5.5.1 + */ + msleep(1); + + /* Bring controller out of reset */ + azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); + + count = 50; + while (! azx_readb(chip, GCTL) && --count) + msleep(1); + + /* Brent Chartrand said to wait >= 540us for codecs to intialize */ + msleep(1); + + /* check to see if controller is ready */ + if (! azx_readb(chip, GCTL)) { + snd_printd("azx_reset: controller not ready!\n"); + return -EBUSY; + } + + /* detect codecs */ + if (! chip->codec_mask) { + chip->codec_mask = azx_readw(chip, STATESTS); + snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); + } + + return 0; +} + + +/* + * Lowlevel interface + */ + +/* enable interrupts */ +static void azx_int_enable(azx_t *chip) +{ + /* enable controller CIE and GIE */ + azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | + ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); +} + +/* disable interrupts */ +static void azx_int_disable(azx_t *chip) +{ + int i; + + /* disable interrupts in stream descriptor */ + for (i = 0; i < MAX_ICH6_DEV; i++) { + azx_dev_t *azx_dev = &chip->azx_dev[i]; + azx_sd_writeb(azx_dev, SD_CTL, + azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK); + } + + /* disable SIE for all streams */ + azx_writeb(chip, INTCTL, 0); + + /* disable controller CIE and GIE */ + azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & + ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); +} + +/* clear interrupts */ +static void azx_int_clear(azx_t *chip) +{ + int i; + + /* clear stream status */ + for (i = 0; i < MAX_ICH6_DEV; i++) { + azx_dev_t *azx_dev = &chip->azx_dev[i]; + azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); + } + + /* clear STATESTS */ + azx_writeb(chip, STATESTS, STATESTS_INT_MASK); + + /* clear rirb status */ + azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); + + /* clear int status */ + azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); +} + +/* start a stream */ +static void azx_stream_start(azx_t *chip, azx_dev_t *azx_dev) +{ + /* enable SIE */ + azx_writeb(chip, INTCTL, + azx_readb(chip, INTCTL) | (1 << azx_dev->index)); + /* set DMA start and interrupt mask */ + azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | + SD_CTL_DMA_START | SD_INT_MASK); +} + +/* stop a stream */ +static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev) +{ + /* stop DMA */ + azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & + ~(SD_CTL_DMA_START | SD_INT_MASK)); + azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ + /* disable SIE */ + azx_writeb(chip, INTCTL, + azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); +} + + +/* + * initialize the chip + */ +static void azx_init_chip(azx_t *chip) +{ + unsigned char tcsel_reg; + + /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) + * TCSEL == Traffic Class Select Register, which sets PCI express QOS + * Ensuring these bits are 0 clears playback static on some HD Audio codecs + */ + pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, &tcsel_reg); + pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, tcsel_reg & 0xf8); + + /* reset controller */ + azx_reset(chip); + + /* initialize interrupts */ + azx_int_clear(chip); + azx_int_enable(chip); + + /* initialize the codec command I/O */ + azx_init_cmd_io(chip); + +#ifdef USE_POSBUF + /* program the position buffer */ + azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); + azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); +#endif +} + + +/* + * interrupt handler + */ +static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) +{ + azx_t *chip = dev_id; + azx_dev_t *azx_dev; + u32 status; + int i; + + spin_lock(&chip->reg_lock); + + status = azx_readl(chip, INTSTS); + if (status == 0) { + spin_unlock(&chip->reg_lock); + return IRQ_NONE; + } + + for (i = 0; i < MAX_ICH6_DEV; i++) { + azx_dev = &chip->azx_dev[i]; + if (status & azx_dev->sd_int_sta_mask) { + azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); + if (azx_dev->substream && azx_dev->running) { + spin_unlock(&chip->reg_lock); + snd_pcm_period_elapsed(azx_dev->substream); + spin_lock(&chip->reg_lock); + } + } + } + + /* clear rirb int */ + status = azx_readb(chip, RIRBSTS); + if (status & RIRB_INT_MASK) { + if (status & RIRB_INT_RESPONSE) + azx_update_rirb(chip); + azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); + } + +#if 0 + /* clear state status int */ + if (azx_readb(chip, STATESTS) & 0x04) + azx_writeb(chip, STATESTS, 0x04); +#endif + spin_unlock(&chip->reg_lock); + + return IRQ_HANDLED; +} + + +/* + * set up BDL entries + */ +static void azx_setup_periods(azx_dev_t *azx_dev) +{ + u32 *bdl = azx_dev->bdl; + dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr; + int idx; + + /* reset BDL address */ + azx_sd_writel(azx_dev, SD_BDLPL, 0); + azx_sd_writel(azx_dev, SD_BDLPU, 0); + + /* program the initial BDL entries */ + for (idx = 0; idx < azx_dev->frags; idx++) { + unsigned int off = idx << 2; /* 4 dword step */ + dma_addr_t addr = dma_addr + idx * azx_dev->fragsize; + /* program the address field of the BDL entry */ + bdl[off] = cpu_to_le32((u32)addr); + bdl[off+1] = cpu_to_le32(upper_32bit(addr)); + + /* program the size field of the BDL entry */ + bdl[off+2] = cpu_to_le32(azx_dev->fragsize); + + /* program the IOC to enable interrupt when buffer completes */ + bdl[off+3] = cpu_to_le32(0x01); + } +} + +/* + * set up the SD for streaming + */ +static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev) +{ + unsigned char val; + int timeout; + + /* make sure the run bit is zero for SD */ + azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~SD_CTL_DMA_START); + /* reset stream */ + azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET); + udelay(3); + timeout = 300; + while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && + --timeout) + ; + val &= ~SD_CTL_STREAM_RESET; + azx_sd_writeb(azx_dev, SD_CTL, val); + udelay(3); + + timeout = 300; + /* waiting for hardware to report that the stream is out of reset */ + while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && + --timeout) + ; + + /* program the stream_tag */ + azx_sd_writel(azx_dev, SD_CTL, + (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK) | + (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT)); + + /* program the length of samples in cyclic buffer */ + azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize); + + /* program the stream format */ + /* this value needs to be the same as the one programmed */ + azx_sd_writew(azx_dev, SD_FORMAT, azx_dev->format_val); + + /* program the stream LVI (last valid index) of the BDL */ + azx_sd_writew(azx_dev, SD_LVI, azx_dev->frags - 1); + + /* program the BDL address */ + /* lower BDL address */ + azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr); + /* upper BDL address */ + azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); + +#ifdef USE_POSBUF + /* enable the position buffer */ + if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) + azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); +#endif + /* set the interrupt enable bits in the descriptor control register */ + azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); + + return 0; +} + + +/* + * Codec initialization + */ + +static int __devinit azx_codec_create(azx_t *chip, const char *model) +{ + struct hda_bus_template bus_temp; + int c, codecs, err; + + memset(&bus_temp, 0, sizeof(bus_temp)); + bus_temp.private_data = chip; + bus_temp.modelname = model; + bus_temp.pci = chip->pci; + bus_temp.ops.command = azx_send_cmd; + bus_temp.ops.get_response = azx_get_response; + + if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) + return err; + + codecs = 0; + for (c = 0; c < AZX_MAX_CODECS; c++) { + if (chip->codec_mask & (1 << c)) { + err = snd_hda_codec_new(chip->bus, c, NULL); + if (err < 0) + continue; + codecs++; + } + } + if (! codecs) { + snd_printk(KERN_ERR SFX "no codecs initialized\n"); + return -ENXIO; + } + + return 0; +} + + +/* + * PCM support + */ + +/* assign a stream for the PCM */ +static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream) +{ + int dev, i; + dev = stream == SNDRV_PCM_STREAM_PLAYBACK ? 4 : 0; + for (i = 0; i < 4; i++, dev++) + if (! chip->azx_dev[dev].opened) { + chip->azx_dev[dev].opened = 1; + return &chip->azx_dev[dev]; + } + return NULL; +} + +/* release the assigned stream */ +static inline void azx_release_device(azx_dev_t *azx_dev) +{ + azx_dev->opened = 0; +} + +static snd_pcm_hardware_t azx_pcm_hw = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = AZX_MAX_BUF_SIZE, + .period_bytes_min = 128, + .period_bytes_max = AZX_MAX_BUF_SIZE / 2, + .periods_min = 2, + .periods_max = AZX_MAX_FRAG, + .fifo_size = 0, +}; + +struct azx_pcm { + azx_t *chip; + struct hda_codec *codec; + struct hda_pcm_stream *hinfo[2]; +}; + +static int azx_pcm_open(snd_pcm_substream_t *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + azx_t *chip = apcm->chip; + azx_dev_t *azx_dev; + snd_pcm_runtime_t *runtime = substream->runtime; + unsigned long flags; + int err; + + down(&chip->open_mutex); + azx_dev = azx_assign_device(chip, substream->stream); + if (azx_dev == NULL) { + up(&chip->open_mutex); + return -EBUSY; + } + runtime->hw = azx_pcm_hw; + runtime->hw.channels_min = hinfo->channels_min; + runtime->hw.channels_max = hinfo->channels_max; + runtime->hw.formats = hinfo->formats; + runtime->hw.rates = hinfo->rates; + snd_pcm_limit_hw_rates(runtime); + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { + azx_release_device(azx_dev); + up(&chip->open_mutex); + return err; + } + spin_lock_irqsave(&chip->reg_lock, flags); + azx_dev->substream = substream; + azx_dev->running = 0; + spin_unlock_irqrestore(&chip->reg_lock, flags); + + runtime->private_data = azx_dev; + up(&chip->open_mutex); + return 0; +} + +static int azx_pcm_close(snd_pcm_substream_t *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + azx_t *chip = apcm->chip; + azx_dev_t *azx_dev = get_azx_dev(substream); + unsigned long flags; + + down(&chip->open_mutex); + spin_lock_irqsave(&chip->reg_lock, flags); + azx_dev->substream = NULL; + azx_dev->running = 0; + spin_unlock_irqrestore(&chip->reg_lock, flags); + azx_release_device(azx_dev); + hinfo->ops.close(hinfo, apcm->codec, substream); + up(&chip->open_mutex); + return 0; +} + +static int azx_pcm_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 azx_pcm_hw_free(snd_pcm_substream_t *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + azx_dev_t *azx_dev = get_azx_dev(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + + /* reset BDL address */ + azx_sd_writel(azx_dev, SD_BDLPL, 0); + azx_sd_writel(azx_dev, SD_BDLPU, 0); + azx_sd_writel(azx_dev, SD_CTL, 0); + + hinfo->ops.cleanup(hinfo, apcm->codec, substream); + + return snd_pcm_lib_free_pages(substream); +} + +static int azx_pcm_prepare(snd_pcm_substream_t *substream) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + azx_t *chip = apcm->chip; + azx_dev_t *azx_dev = get_azx_dev(substream); + struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; + snd_pcm_runtime_t *runtime = substream->runtime; + + azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); + azx_dev->fragsize = snd_pcm_lib_period_bytes(substream); + azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize; + azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, + runtime->channels, + runtime->format, + hinfo->maxbps); + if (! azx_dev->format_val) { + snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n", + runtime->rate, runtime->channels, runtime->format); + return -EINVAL; + } + + snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, format=0x%x\n", + azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); + azx_setup_periods(azx_dev); + azx_setup_controller(chip, azx_dev); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; + else + azx_dev->fifo_size = 0; + + return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, + azx_dev->format_val, substream); +} + +static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) +{ + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + azx_dev_t *azx_dev = get_azx_dev(substream); + azx_t *chip = apcm->chip; + int err = 0; + + spin_lock(&chip->reg_lock); + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_START: + azx_stream_start(chip, azx_dev); + azx_dev->running = 1; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + azx_stream_stop(chip, azx_dev); + azx_dev->running = 0; + break; + default: + err = -EINVAL; + } + spin_unlock(&chip->reg_lock); + if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH || + cmd == SNDRV_PCM_TRIGGER_STOP) { + int timeout = 5000; + while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout) + ; + } + return err; +} + +static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) +{ + azx_dev_t *azx_dev = get_azx_dev(substream); + unsigned int pos; + +#ifdef USE_POSBUF + /* use the position buffer */ + pos = *azx_dev->posbuf; +#else + /* read LPIB */ + pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size; +#endif + if (pos >= azx_dev->bufsize) + pos = 0; + return bytes_to_frames(substream->runtime, pos); +} + +static snd_pcm_ops_t azx_pcm_ops = { + .open = azx_pcm_open, + .close = azx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = azx_pcm_hw_params, + .hw_free = azx_pcm_hw_free, + .prepare = azx_pcm_prepare, + .trigger = azx_pcm_trigger, + .pointer = azx_pcm_pointer, +}; + +static void azx_pcm_free(snd_pcm_t *pcm) +{ + kfree(pcm->private_data); +} + +static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec, + struct hda_pcm *cpcm, int pcm_dev) +{ + int err; + snd_pcm_t *pcm; + struct azx_pcm *apcm; + + snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL); + snd_assert(cpcm->name, return -EINVAL); + + err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, + cpcm->stream[0].substreams, cpcm->stream[1].substreams, + &pcm); + if (err < 0) + return err; + strcpy(pcm->name, cpcm->name); + apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); + if (apcm == NULL) + return -ENOMEM; + apcm->chip = chip; + apcm->codec = codec; + apcm->hinfo[0] = &cpcm->stream[0]; + apcm->hinfo[1] = &cpcm->stream[1]; + pcm->private_data = apcm; + pcm->private_free = azx_pcm_free; + if (cpcm->stream[0].substreams) + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); + if (cpcm->stream[1].substreams) + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(chip->pci), + 1024 * 64, 1024 * 128); + chip->pcm[pcm_dev] = pcm; + + return 0; +} + +static int __devinit azx_pcm_create(azx_t *chip) +{ + struct list_head *p; + struct hda_codec *codec; + int c, err; + int pcm_dev; + + if ((err = snd_hda_build_pcms(chip->bus)) < 0) + return err; + + pcm_dev = 0; + list_for_each(p, &chip->bus->codec_list) { + codec = list_entry(p, struct hda_codec, list); + for (c = 0; c < codec->num_pcms; c++) { + if (pcm_dev >= AZX_MAX_PCMS) { + snd_printk(KERN_ERR SFX "Too many PCMs\n"); + return -EINVAL; + } + err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); + if (err < 0) + return err; + pcm_dev++; + } + } + return 0; +} + +/* + * mixer creation - all stuff is implemented in hda module + */ +static int __devinit azx_mixer_create(azx_t *chip) +{ + return snd_hda_build_controls(chip->bus); +} + + +/* + * initialize SD streams + */ +static int __devinit azx_init_stream(azx_t *chip) +{ + int i; + + /* initialize each stream (aka device) + * assign the starting bdl address to each stream (device) and initialize + */ + for (i = 0; i < MAX_ICH6_DEV; i++) { + unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); + azx_dev_t *azx_dev = &chip->azx_dev[i]; + azx_dev->bdl = (u32 *)(chip->bdl.area + off); + azx_dev->bdl_addr = chip->bdl.addr + off; +#ifdef USE_POSBUF + azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); +#endif + /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ + azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); + /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ + azx_dev->sd_int_sta_mask = 1 << i; + /* stream tag: must be non-zero and unique */ + azx_dev->index = i; + azx_dev->stream_tag = i + 1; + } + + return 0; +} + + +#ifdef CONFIG_PM +/* + * power management + */ +static int azx_suspend(snd_card_t *card, pm_message_t state) +{ + azx_t *chip = card->pm_private_data; + int i; + + for (i = 0; i < chip->pcm_devs; i++) + if (chip->pcm[i]) + snd_pcm_suspend_all(chip->pcm[i]); + snd_hda_suspend(chip->bus, state); + azx_free_cmd_io(chip); + pci_disable_device(chip->pci); + return 0; +} + +static int azx_resume(snd_card_t *card) +{ + azx_t *chip = card->pm_private_data; + + pci_enable_device(chip->pci); + pci_set_master(chip->pci); + azx_init_chip(chip); + snd_hda_resume(chip->bus); + return 0; +} +#endif /* CONFIG_PM */ + + +/* + * destructor + */ +static int azx_free(azx_t *chip) +{ + if (chip->remap_addr) { + int i; + + for (i = 0; i < MAX_ICH6_DEV; i++) + azx_stream_stop(chip, &chip->azx_dev[i]); + + /* disable interrupts */ + azx_int_disable(chip); + azx_int_clear(chip); + + /* disable CORB/RIRB */ + azx_free_cmd_io(chip); + + /* disable position buffer */ + azx_writel(chip, DPLBASE, 0); + azx_writel(chip, DPUBASE, 0); + + /* wait a little for interrupts to finish */ + msleep(1); + + iounmap(chip->remap_addr); + } + + if (chip->irq >= 0) + free_irq(chip->irq, (void*)chip); + + if (chip->bdl.area) + snd_dma_free_pages(&chip->bdl); + if (chip->rb.area) + snd_dma_free_pages(&chip->rb); +#ifdef USE_POSBUF + if (chip->posbuf.area) + snd_dma_free_pages(&chip->posbuf); +#endif + pci_release_regions(chip->pci); + pci_disable_device(chip->pci); + kfree(chip); + + return 0; +} + +static int azx_dev_free(snd_device_t *device) +{ + return azx_free(device->device_data); +} + +/* + * constructor + */ +static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip) +{ + azx_t *chip; + int err = 0; + static snd_device_ops_t ops = { + .dev_free = azx_dev_free, + }; + + *rchip = NULL; + + if ((err = pci_enable_device(pci)) < 0) + return err; + + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); + + if (NULL == chip) { + snd_printk(KERN_ERR SFX "cannot allocate chip\n"); + pci_disable_device(pci); + return -ENOMEM; + } + + spin_lock_init(&chip->reg_lock); + init_MUTEX(&chip->open_mutex); + chip->card = card; + chip->pci = pci; + chip->irq = -1; + + if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { + kfree(chip); + pci_disable_device(pci); + return err; + } + + chip->addr = pci_resource_start(pci,0); + chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); + if (chip->remap_addr == NULL) { + snd_printk(KERN_ERR SFX "ioremap error\n"); + err = -ENXIO; + goto errout; + } + + if (request_irq(pci->irq, azx_interrupt, SA_INTERRUPT|SA_SHIRQ, + "HDA Intel", (void*)chip)) { + snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); + err = -EBUSY; + goto errout; + } + chip->irq = pci->irq; + + pci_set_master(pci); + synchronize_irq(chip->irq); + + /* allocate memory for the BDL for each stream */ + if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), + PAGE_SIZE, &chip->bdl)) < 0) { + snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); + goto errout; + } +#ifdef USE_POSBUF + /* allocate memory for the position buffer */ + if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), + MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { + snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); + goto errout; + } +#endif + /* allocate CORB/RIRB */ + if ((err = azx_alloc_cmd_io(chip)) < 0) + goto errout; + + /* initialize streams */ + azx_init_stream(chip); + + /* initialize chip */ + azx_init_chip(chip); + + /* codec detection */ + if (! chip->codec_mask) { + snd_printk(KERN_ERR SFX "no codecs found!\n"); + err = -ENODEV; + goto errout; + } + + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) <0) { + snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); + goto errout; + } + + *rchip = chip; + return 0; + + errout: + azx_free(chip); + return err; +} + +static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) +{ + static int dev; + snd_card_t *card; + azx_t *chip; + int err = 0; + + if (dev >= SNDRV_CARDS) + return -ENODEV; + if (! enable[dev]) { + dev++; + return -ENOENT; + } + + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + if (NULL == card) { + snd_printk(KERN_ERR SFX "Error creating card!\n"); + return -ENOMEM; + } + + if ((err = azx_create(card, pci, &chip)) < 0) { + snd_card_free(card); + return err; + } + + strcpy(card->driver, "HDA-Intel"); + strcpy(card->shortname, "HDA Intel"); + sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq); + + /* create codec instances */ + if ((err = azx_codec_create(chip, model[dev])) < 0) { + snd_card_free(card); + return err; + } + + /* create PCM streams */ + if ((err = azx_pcm_create(chip)) < 0) { + snd_card_free(card); + return err; + } + + /* create mixer controls */ + if ((err = azx_mixer_create(chip)) < 0) { + snd_card_free(card); + return err; + } + + snd_card_set_pm_callback(card, azx_suspend, azx_resume, chip); + snd_card_set_dev(card, &pci->dev); + + if ((err = snd_card_register(card)) < 0) { + snd_card_free(card); + return err; + } + + pci_set_drvdata(pci, card); + dev++; + + return err; +} + +static void __devexit azx_remove(struct pci_dev *pci) +{ + snd_card_free(pci_get_drvdata(pci)); + pci_set_drvdata(pci, NULL); +} + +/* PCI IDs */ +static struct pci_device_id azx_ids[] = { + { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */ + { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */ + { 0, } +}; +MODULE_DEVICE_TABLE(pci, azx_ids); + +/* pci_driver definition */ +static struct pci_driver driver = { + .name = "HDA Intel", + .id_table = azx_ids, + .probe = azx_probe, + .remove = __devexit_p(azx_remove), + SND_PCI_PM_CALLBACKS +}; + +static int __init alsa_card_azx_init(void) +{ + return pci_module_init(&driver); +} + +static void __exit alsa_card_azx_exit(void) +{ + pci_unregister_driver(&driver); +} + +module_init(alsa_card_azx_init) +module_exit(alsa_card_azx_exit) diff -Nru a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_local.h 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,161 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * Local helper functions + * + * Copyright (c) 2004 Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SOUND_HDA_LOCAL_H +#define __SOUND_HDA_LOCAL_H + +/* + * for mixer controls + */ +#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) +#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ + .info = snd_hda_mixer_amp_volume_info, \ + .get = snd_hda_mixer_amp_volume_get, \ + .put = snd_hda_mixer_amp_volume_put, \ + .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } +#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ + HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) +#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ + HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) +#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ + HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) +#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ + .info = snd_hda_mixer_amp_switch_info, \ + .get = snd_hda_mixer_amp_switch_get, \ + .put = snd_hda_mixer_amp_switch_put, \ + .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } +#define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \ + HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) +#define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \ + HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction) +#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ + HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) + +int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo); +int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); +int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); +int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo); +int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); +int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); + +int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); +int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); + +/* + * input MUX helper + */ +#define HDA_MAX_NUM_INPUTS 8 +struct hda_input_mux_item { + const char *label; + unsigned int index; +}; +struct hda_input_mux { + unsigned int num_items; + struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; +}; + +int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo); +int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, + snd_ctl_elem_value_t *ucontrol, hda_nid_t nid, + unsigned int *cur_val); + +/* + * Multi-channel / digital-out PCM helper + */ + +enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */ +enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */ + +struct hda_multi_out { + int num_dacs; /* # of DACs, must be more than 1 */ + hda_nid_t *dac_nids; /* DAC list */ + hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ + hda_nid_t dig_out_nid; /* digital out audio widget */ + int max_channels; /* currently supported analog channels */ + int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ +}; + +int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); +int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); +int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, + snd_pcm_substream_t *substream); +int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream); +int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout); + +/* + * generic codec parser + */ +int snd_hda_parse_generic_codec(struct hda_codec *codec); + +/* + * generic proc interface + */ +#ifdef CONFIG_PROC_FS +int snd_hda_codec_proc_new(struct hda_codec *codec); +#else +static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } +#endif + +/* + * Misc + */ +struct hda_board_config { + const char *modelname; + int config; + unsigned short pci_vendor; + unsigned short pci_device; +}; + +int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl); +int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew); + +/* + * power management + */ +#ifdef CONFIG_PM +int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew); +int snd_hda_resume_spdif_out(struct hda_codec *codec); +int snd_hda_resume_spdif_in(struct hda_codec *codec); +#endif + +/* + * unsolicited event handler + */ + +#define HDA_UNSOL_QUEUE_SIZE 64 + +struct hda_bus_unsolicited { + /* ring buffer */ + u32 queue[HDA_UNSOL_QUEUE_SIZE * 2]; + unsigned int rp, wp; + + /* workqueue */ + struct workqueue_struct *workq; + struct work_struct work; +}; + +#endif /* __SOUND_HDA_LOCAL_H */ diff -Nru a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_patch.h 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,14 @@ +/* + * HDA Patches - included by hda_codec.c + */ + +/* Realtek codecs */ +extern struct hda_codec_preset snd_hda_preset_realtek[]; +/* C-Media codecs */ +extern struct hda_codec_preset snd_hda_preset_cmedia[]; + +static const struct hda_codec_preset *hda_preset_tables[] = { + snd_hda_preset_realtek, + snd_hda_preset_cmedia, + NULL +}; diff -Nru a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/hda_proc.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,298 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * Generic proc interface + * + * Copyright (c) 2004 Takashi Iwai + * + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver 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 +#include +#include +#include +#include "hda_codec.h" + +static const char *get_wid_type_name(unsigned int wid_value) +{ + static char *names[16] = { + [AC_WID_AUD_OUT] = "Audio Output", + [AC_WID_AUD_IN] = "Audio Input", + [AC_WID_AUD_MIX] = "Audio Mixer", + [AC_WID_AUD_SEL] = "Audio Selector", + [AC_WID_PIN] = "Pin Complex", + [AC_WID_POWER] = "Power Widget", + [AC_WID_VOL_KNB] = "Volume Knob Widget", + [AC_WID_BEEP] = "Beep Generator Widget", + [AC_WID_VENDOR] = "Vendor Defined Widget", + }; + wid_value &= 0xf; + if (names[wid_value]) + return names[wid_value]; + else + return "UNKOWN Widget"; +} + +static void print_amp_caps(snd_info_buffer_t *buffer, + struct hda_codec *codec, hda_nid_t nid, int dir) +{ + unsigned int caps; + if (dir == HDA_OUTPUT) + caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP); + else + caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP); + if (caps == -1 || caps == 0) { + snd_iprintf(buffer, "N/A\n"); + return; + } + snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, mute=%x\n", + caps & AC_AMPCAP_OFFSET, + (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT, + (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT, + (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT); +} + +static void print_amp_vals(snd_info_buffer_t *buffer, + struct hda_codec *codec, hda_nid_t nid, + int dir, int stereo) +{ + unsigned int val; + if (stereo) { + val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, + AC_AMP_GET_LEFT | + (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : + AC_AMP_GET_INPUT)); + snd_iprintf(buffer, "0x%02x ", val); + } + val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, + AC_AMP_GET_RIGHT | + (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : + AC_AMP_GET_INPUT)); + snd_iprintf(buffer, "0x%02x\n", val); +} + +static void print_pcm_caps(snd_info_buffer_t *buffer, + struct hda_codec *codec, hda_nid_t nid) +{ + unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM); + unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); + if (pcm == -1 || stream == -1) { + snd_iprintf(buffer, "N/A\n"); + return; + } + snd_iprintf(buffer, "rates 0x%03x, bits 0x%02x, types 0x%x\n", + pcm & AC_SUPPCM_RATES, (pcm >> 16) & 0xff, stream & 0xf); +} + +static const char *get_jack_location(u32 cfg) +{ + static char *bases[7] = { + "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", + }; + static unsigned char specials_idx[] = { + 0x07, 0x08, + 0x17, 0x18, 0x19, + 0x37, 0x38 + }; + static char *specials[] = { + "Rear Panel", "Drive Bar", + "Riser", "HDMI", "ATAPI", + "Mobile-In", "Mobile-Out" + }; + int i; + cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; + if ((cfg & 0x0f) < 7) + return bases[cfg & 0x0f]; + for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { + if (cfg == specials_idx[i]) + return specials[i]; + } + return "UNKNOWN"; +} + +static const char *get_jack_connection(u32 cfg) +{ + static char *names[16] = { + "Unknown", "1/8", "1/4", "ATAPI", + "RCA", "Optical","Digital", "Analog", + "DIN", "XLR", "RJ11", "Comb", + NULL, NULL, NULL, "Other" + }; + cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT; + if (names[cfg]) + return names[cfg]; + else + return "UNKNOWN"; +} + +static const char *get_jack_color(u32 cfg) +{ + static char *names[16] = { + "Unknown", "Black", "Grey", "Blue", + "Green", "Red", "Orange", "Yellow", + "Purple", "Pink", NULL, NULL, + NULL, NULL, "White", "Other", + }; + cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT; + if (names[cfg]) + return names[cfg]; + else + return "UNKNOWN"; +} + +static void print_pin_caps(snd_info_buffer_t *buffer, + struct hda_codec *codec, hda_nid_t nid) +{ + static char *jack_types[16] = { + "Line Out", "Speaker", "HP Out", "CD", + "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", + "Line In", "Aux", "Mic", "Telephony", + "SPDIF In", "Digitial In", "Reserved", "Other" + }; + static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; + unsigned int caps; + + caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + snd_iprintf(buffer, " Pincap 0x08%x:", caps); + if (caps & AC_PINCAP_IN) + snd_iprintf(buffer, " IN"); + if (caps & AC_PINCAP_OUT) + snd_iprintf(buffer, " OUT"); + if (caps & AC_PINCAP_HP_DRV) + snd_iprintf(buffer, " HP"); + snd_iprintf(buffer, "\n"); + caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); + snd_iprintf(buffer, " Pin Default 0x%08x: %s at %s %s\n", caps, + jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], + jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], + get_jack_location(caps)); + snd_iprintf(buffer, " Conn = %s, Color = %s\n", + get_jack_connection(caps), + get_jack_color(caps)); +} + + +static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) +{ + struct hda_codec *codec = entry->private_data; + char buf[32]; + hda_nid_t nid; + int i, nodes; + + snd_hda_get_codec_name(codec, buf, sizeof(buf)); + snd_iprintf(buffer, "Codec: %s\n", buf); + snd_iprintf(buffer, "Address: %d\n", codec->addr); + snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); + snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); + snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); + snd_iprintf(buffer, "Default PCM: "); + print_pcm_caps(buffer, codec, codec->afg); + snd_iprintf(buffer, "Default Amp-In caps: "); + print_amp_caps(buffer, codec, codec->afg, HDA_INPUT); + snd_iprintf(buffer, "Default Amp-Out caps: "); + print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT); + + nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); + if (! nid || nodes < 0) { + snd_iprintf(buffer, "Invalid AFG subtree\n"); + return; + } + for (i = 0; i < nodes; i++, nid++) { + unsigned int wid_caps = snd_hda_param_read(codec, nid, + AC_PAR_AUDIO_WIDGET_CAP); + unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, + get_wid_type_name(wid_type), wid_caps); + if (wid_caps & AC_WCAP_STEREO) + snd_iprintf(buffer, " Stereo"); + else + snd_iprintf(buffer, " Mono"); + if (wid_caps & AC_WCAP_DIGITAL) + snd_iprintf(buffer, " Digital"); + if (wid_caps & AC_WCAP_IN_AMP) + snd_iprintf(buffer, " Amp-In"); + if (wid_caps & AC_WCAP_OUT_AMP) + snd_iprintf(buffer, " Amp-Out"); + snd_iprintf(buffer, "\n"); + + if (wid_caps & AC_WCAP_IN_AMP) { + snd_iprintf(buffer, " Amp-In caps: "); + print_amp_caps(buffer, codec, nid, HDA_INPUT); + snd_iprintf(buffer, " Amp-In vals: "); + print_amp_vals(buffer, codec, nid, HDA_INPUT, + wid_caps & AC_WCAP_STEREO); + } + if (wid_caps & AC_WCAP_OUT_AMP) { + snd_iprintf(buffer, " Amp-Out caps: "); + print_amp_caps(buffer, codec, nid, HDA_OUTPUT); + snd_iprintf(buffer, " Amp-Out vals: "); + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, + wid_caps & AC_WCAP_STEREO); + } + + if (wid_type == AC_WID_PIN) { + unsigned int pinctls; + print_pin_caps(buffer, codec, nid); + pinctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); + if (pinctls & AC_PINCTL_IN_EN) + snd_iprintf(buffer, " IN"); + if (pinctls & AC_PINCTL_OUT_EN) + snd_iprintf(buffer, " OUT"); + if (pinctls & AC_PINCTL_HP_EN) + snd_iprintf(buffer, " HP"); + snd_iprintf(buffer, "\n"); + } + + if ((wid_type == AC_WID_AUD_OUT || wid_type == AC_WID_AUD_IN) && + (wid_caps & AC_WCAP_FORMAT_OVRD)) { + snd_iprintf(buffer, " PCM: "); + print_pcm_caps(buffer, codec, nid); + } + + if (wid_caps & AC_WCAP_CONN_LIST) { + hda_nid_t conn[HDA_MAX_CONNECTIONS]; + int c, conn_len; + conn_len = snd_hda_get_connections(codec, nid, conn, + HDA_MAX_CONNECTIONS); + snd_iprintf(buffer, " Connection: %d\n", conn_len); + snd_iprintf(buffer, " "); + for (c = 0; c < conn_len; c++) + snd_iprintf(buffer, " 0x%02x", conn[c]); + snd_iprintf(buffer, "\n"); + } + } +} + +/* + * create a proc read + */ +int snd_hda_codec_proc_new(struct hda_codec *codec) +{ + char name[32]; + snd_info_entry_t *entry; + int err; + + snprintf(name, sizeof(name), "codec#%d", codec->addr); + err = snd_card_proc_new(codec->bus->card, name, &entry); + if (err < 0) + return err; + + snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info); + return 0; +} + diff -Nru a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/patch_cmedia.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,620 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * HD audio interface patch for C-Media CMI9880 + * + * Copyright (c) 2004 Takashi Iwai + * + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver 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 +#include +#include +#include +#include +#include +#include "hda_codec.h" +#include "hda_local.h" + + +/* board config type */ +enum { + CMI_MINIMAL, /* back 3-jack */ + CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */ + CMI_FULL, /* back 6-jack + front-panel 2-jack */ + CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ + CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ +}; + +struct cmi_spec { + int board_config; + unsigned int surr_switch: 1; /* switchable line,mic */ + unsigned int no_line_in: 1; /* no line-in (5-jack) */ + unsigned int front_panel: 1; /* has front-panel 2-jack */ + + /* playback */ + struct hda_multi_out multiout; + + /* capture */ + hda_nid_t *adc_nids; + hda_nid_t dig_in_nid; + + /* capture source */ + const struct hda_input_mux *input_mux; + unsigned int cur_mux[2]; + + /* channel mode */ + unsigned int num_ch_modes; + unsigned int cur_ch_mode; + const struct cmi_channel_mode *channel_modes; + + struct hda_pcm pcm_rec[2]; /* PCM information */ +}; + +/* + * input MUX + */ +static int cmi_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct cmi_spec *spec = codec->spec; + return snd_hda_input_mux_info(spec->input_mux, uinfo); +} + +static int cmi_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct cmi_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; + return 0; +} + +static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct cmi_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, + spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); +} + +/* + * shared line-in, mic for surrounds + */ + +/* 3-stack / 2 channel */ +static struct hda_verb cmi9880_ch2_init[] = { + /* set line-in PIN for input */ + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, + /* set mic PIN for input, also enable vref */ + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, + /* route front PCM (DAC1) to HP */ + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, + {} +}; + +/* 3-stack / 6 channel */ +static struct hda_verb cmi9880_ch6_init[] = { + /* set line-in PIN for input */ + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* set mic PIN for input, also enable vref */ + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* route front PCM (DAC1) to HP */ + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, + {} +}; + +/* 3-stack+front / 8 channel */ +static struct hda_verb cmi9880_ch8_init[] = { + /* set line-in PIN for input */ + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* set mic PIN for input, also enable vref */ + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* route rear-surround PCM (DAC4) to HP */ + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, + {} +}; + +struct cmi_channel_mode { + unsigned int channels; + const struct hda_verb *sequence; +}; + +static struct cmi_channel_mode cmi9880_channel_modes[3] = { + { 2, cmi9880_ch2_init }, + { 6, cmi9880_ch6_init }, + { 8, cmi9880_ch8_init }, +}; + +static int cmi_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct cmi_spec *spec = codec->spec; + + snd_assert(spec->channel_modes, return -EINVAL); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = spec->num_ch_modes; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + sprintf(uinfo->value.enumerated.name, "%dch", + spec->channel_modes[uinfo->value.enumerated.item].channels); + return 0; +} + +static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct cmi_spec *spec = codec->spec; + + ucontrol->value.enumerated.item[0] = spec->cur_ch_mode; + return 0; +} + +static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct cmi_spec *spec = codec->spec; + + snd_assert(spec->channel_modes, return -EINVAL); + if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes) + ucontrol->value.enumerated.item[0] = spec->num_ch_modes; + if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode && + ! codec->in_resume) + return 0; + + spec->cur_ch_mode = ucontrol->value.enumerated.item[0]; + snd_hda_sequence_write(codec, spec->channel_modes[spec->cur_ch_mode].sequence); + spec->multiout.max_channels = spec->channel_modes[spec->cur_ch_mode].channels; + return 1; +} + +/* + */ +static snd_kcontrol_new_t cmi9880_basic_mixer[] = { + /* CMI9880 has no playback volumes! */ + HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */ + HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + * FIXME: the controls appear in the "playback" view! + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = cmi_mux_enum_info, + .get = cmi_mux_enum_get, + .put = cmi_mux_enum_put, + }, + HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT), + { } /* end */ +}; + +/* + * shared I/O pins + */ +static snd_kcontrol_new_t cmi9880_ch_mode_mixer[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Channel Mode", + .info = cmi_ch_mode_info, + .get = cmi_ch_mode_get, + .put = cmi_ch_mode_put, + }, + { } /* end */ +}; + +/* AUD-in selections: + * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20 + */ +static struct hda_input_mux cmi9880_basic_mux = { + .num_items = 4, + .items = { + { "Front Mic", 0x5 }, + { "Rear Mic", 0x2 }, + { "Line", 0x1 }, + { "CD", 0x7 }, + } +}; + +static struct hda_input_mux cmi9880_no_line_mux = { + .num_items = 3, + .items = { + { "Front Mic", 0x5 }, + { "Rear Mic", 0x2 }, + { "CD", 0x7 }, + } +}; + +/* front, rear, clfe, rear_surr */ +static hda_nid_t cmi9880_dac_nids[4] = { + 0x03, 0x04, 0x05, 0x06 +}; +/* ADC0, ADC1 */ +static hda_nid_t cmi9880_adc_nids[2] = { + 0x08, 0x09 +}; + +#define CMI_DIG_OUT_NID 0x07 +#define CMI_DIG_IN_NID 0x0a + +/* + */ +static struct hda_verb cmi9880_basic_init[] = { + /* port-D for line out (rear panel) */ + { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-E for HP out (front panel) */ + { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* route front PCM to HP */ + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, + /* port-A for surround (rear panel) */ + { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-G for CLFE (rear panel) */ + { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-H for side (rear panel) */ + { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-C for line-in (rear panel) */ + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, + /* port-B for mic-in (rear panel) with vref */ + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, + /* port-F for mic-in (front panel) with vref */ + { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, + /* CD-in */ + { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, + /* route front mic to ADC1/2 */ + { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, + { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, + {} /* terminator */ +}; + +static struct hda_verb cmi9880_allout_init[] = { + /* port-D for line out (rear panel) */ + { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-E for HP out (front panel) */ + { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* route front PCM to HP */ + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, + /* port-A for side (rear panel) */ + { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-G for CLFE (rear panel) */ + { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-C for surround (rear panel) */ + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, + /* port-B for mic-in (rear panel) with vref */ + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, + /* port-F for mic-in (front panel) with vref */ + { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, + /* CD-in */ + { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, + /* route front mic to ADC1/2 */ + { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, + { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, + {} /* terminator */ +}; + +/* + */ +static int cmi9880_build_controls(struct hda_codec *codec) +{ + struct cmi_spec *spec = codec->spec; + int err; + + err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); + if (err < 0) + return err; + if (spec->surr_switch) { + err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer); + if (err < 0) + return err; + } + if (spec->multiout.dig_out_nid) { + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); + if (err < 0) + return err; + } + if (spec->dig_in_nid) { + err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); + if (err < 0) + return err; + } + return 0; +} + +static int cmi9880_init(struct hda_codec *codec) +{ + struct cmi_spec *spec = codec->spec; + if (spec->board_config == CMI_ALLOUT) + snd_hda_sequence_write(codec, cmi9880_allout_init); + else + snd_hda_sequence_write(codec, cmi9880_basic_init); + return 0; +} + +#ifdef CONFIG_PM +/* + * resume + */ +static int cmi9880_resume(struct hda_codec *codec) +{ + struct cmi_spec *spec = codec->spec; + + cmi9880_init(codec); + snd_hda_resume_ctls(codec, cmi9880_basic_mixer); + if (spec->surr_switch) + snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer); + if (spec->multiout.dig_out_nid) + snd_hda_resume_spdif_out(codec); + if (spec->dig_in_nid) + snd_hda_resume_spdif_in(codec); + + return 0; +} +#endif + +/* + * Analog playback callbacks + */ +static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); +} + +static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} + +static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); +} + +/* + * Digital out + */ +static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); +} + +static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); +} + +/* + * Analog capture + */ +static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], + stream_tag, 0, format); + return 0; +} + +static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct cmi_spec *spec = codec->spec; + + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); + return 0; +} + + +/* + */ +static struct hda_pcm_stream cmi9880_pcm_analog_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 8, + .nid = 0x03, /* NID to query formats and rates */ + .ops = { + .open = cmi9880_playback_pcm_open, + .prepare = cmi9880_playback_pcm_prepare, + .cleanup = cmi9880_playback_pcm_cleanup + }, +}; + +static struct hda_pcm_stream cmi9880_pcm_analog_capture = { + .substreams = 2, + .channels_min = 2, + .channels_max = 2, + .nid = 0x08, /* NID to query formats and rates */ + .ops = { + .prepare = cmi9880_capture_pcm_prepare, + .cleanup = cmi9880_capture_pcm_cleanup + }, +}; + +static struct hda_pcm_stream cmi9880_pcm_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + /* NID is set in cmi9880_build_pcms */ + .ops = { + .open = cmi9880_dig_playback_pcm_open, + .close = cmi9880_dig_playback_pcm_close + }, +}; + +static struct hda_pcm_stream cmi9880_pcm_digital_capture = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + /* NID is set in cmi9880_build_pcms */ +}; + +static int cmi9880_build_pcms(struct hda_codec *codec) +{ + struct cmi_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; + + codec->num_pcms = 1; + codec->pcm_info = info; + + info->name = "CMI9880"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback; + info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture; + + if (spec->multiout.dig_out_nid || spec->dig_in_nid) { + codec->num_pcms++; + info++; + info->name = "CMI9880 Digital"; + if (spec->multiout.dig_out_nid) { + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; + } + if (spec->dig_in_nid) { + info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture; + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; + } + } + + return 0; +} + +static void cmi9880_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} + +/* + */ + +static struct hda_board_config cmi9880_cfg_tbl[] = { + { .modelname = "minimal", .config = CMI_MINIMAL }, + { .modelname = "min_fp", .config = CMI_MIN_FP }, + { .modelname = "full", .config = CMI_FULL }, + { .modelname = "full_dig", .config = CMI_FULL_DIG }, + { .modelname = "allout", .config = CMI_ALLOUT }, + {} /* terminator */ +}; + +static struct hda_codec_ops cmi9880_patch_ops = { + .build_controls = cmi9880_build_controls, + .build_pcms = cmi9880_build_pcms, + .init = cmi9880_init, + .free = cmi9880_free, +#ifdef CONFIG_PM + .resume = cmi9880_resume, +#endif +}; + +static int patch_cmi9880(struct hda_codec *codec) +{ + struct cmi_spec *spec; + + spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); + if (spec->board_config < 0) { + snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); + spec->board_config = CMI_MINIMAL; + } + + switch (spec->board_config) { + case CMI_MINIMAL: + case CMI_MIN_FP: + spec->surr_switch = 1; + if (spec->board_config == CMI_MINIMAL) + spec->num_ch_modes = 2; + else { + spec->front_panel = 1; + spec->num_ch_modes = 3; + } + spec->channel_modes = cmi9880_channel_modes; + spec->multiout.max_channels = cmi9880_channel_modes[0].channels; + spec->input_mux = &cmi9880_basic_mux; + break; + case CMI_FULL: + case CMI_FULL_DIG: + spec->front_panel = 1; + spec->multiout.max_channels = 8; + spec->input_mux = &cmi9880_basic_mux; + if (spec->board_config == CMI_FULL_DIG) { + spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; + spec->dig_in_nid = CMI_DIG_IN_NID; + } + break; + case CMI_ALLOUT: + spec->front_panel = 1; + spec->multiout.max_channels = 8; + spec->no_line_in = 1; + spec->input_mux = &cmi9880_no_line_mux; + spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; + break; + } + + spec->multiout.num_dacs = 4; + spec->multiout.dac_nids = cmi9880_dac_nids; + + spec->adc_nids = cmi9880_adc_nids; + + codec->patch_ops = cmi9880_patch_ops; + + return 0; +} + +/* + * patch entries + */ +struct hda_codec_preset snd_hda_preset_cmedia[] = { + { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 }, + {} /* terminator */ +}; diff -Nru a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/hda/patch_realtek.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,1477 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * HD audio interface patch for ALC 260/880/882 codecs + * + * Copyright (c) 2004 PeiSen Hou + * Takashi Iwai + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver 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 +#include +#include +#include +#include +#include +#include "hda_codec.h" +#include "hda_local.h" + + +/* ALC880 board config type */ +enum { + ALC880_MINIMAL, + ALC880_3ST, + ALC880_3ST_DIG, + ALC880_5ST, + ALC880_5ST_DIG, + ALC880_W810, +}; + +struct alc_spec { + /* codec parameterization */ + unsigned int front_panel: 1; + + snd_kcontrol_new_t* mixers[2]; + unsigned int num_mixers; + + struct hda_verb *init_verbs; + + char* stream_name_analog; + struct hda_pcm_stream *stream_analog_playback; + struct hda_pcm_stream *stream_analog_capture; + + char* stream_name_digital; + struct hda_pcm_stream *stream_digital_playback; + struct hda_pcm_stream *stream_digital_capture; + + /* playback */ + struct hda_multi_out multiout; + + /* capture */ + unsigned int num_adc_nids; + hda_nid_t *adc_nids; + hda_nid_t dig_in_nid; + + /* capture source */ + const struct hda_input_mux *input_mux; + unsigned int cur_mux[3]; + + /* channel model */ + const struct alc_channel_mode *channel_mode; + int num_channel_mode; + + /* PCM information */ + struct hda_pcm pcm_rec[2]; +}; + +/* DAC/ADC assignment */ + +static hda_nid_t alc880_dac_nids[4] = { + /* front, rear, clfe, rear_surr */ + 0x02, 0x05, 0x04, 0x03 +}; + +static hda_nid_t alc880_w810_dac_nids[3] = { + /* front, rear/surround, clfe */ + 0x02, 0x03, 0x04 +}; + +static hda_nid_t alc880_adc_nids[3] = { + /* ADC0-2 */ + 0x07, 0x08, 0x09, +}; + +#define ALC880_DIGOUT_NID 0x06 +#define ALC880_DIGIN_NID 0x0a + +static hda_nid_t alc260_dac_nids[1] = { + /* front */ + 0x02, +}; + +static hda_nid_t alc260_adc_nids[2] = { + /* ADC0-1 */ + 0x04, 0x05, +}; + +#define ALC260_DIGOUT_NID 0x03 +#define ALC260_DIGIN_NID 0x06 + +static struct hda_input_mux alc880_capture_source = { + .num_items = 4, + .items = { + { "Mic", 0x0 }, + { "Front Mic", 0x3 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + +static struct hda_input_mux alc260_capture_source = { + .num_items = 3, + .items = { + { "Mic", 0x0 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + +/* + * input MUX handling + */ +static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + return snd_hda_input_mux_info(spec->input_mux, uinfo); +} + +static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; + return 0; +} + +static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, + spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); +} + +/* + * channel mode setting + */ +struct alc_channel_mode { + int channels; + const struct hda_verb *sequence; +}; + + +/* + * channel source setting (2/6 channel selection for 3-stack) + */ + +/* + * set the path ways for 2 channel output + * need to set the codec line out and mic 1 pin widgets to inputs + */ +static struct hda_verb alc880_threestack_ch2_init[] = { + /* set pin widget 1Ah (line in) for input */ + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, + /* set pin widget 18h (mic1) for input, for mic also enable the vref */ + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, + /* mute the output for Line In PW */ + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, + /* mute for Mic1 PW */ + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, + { } /* end */ +}; + +/* + * 6ch mode + * need to set the codec line out and mic 1 pin widgets to outputs + */ +static struct hda_verb alc880_threestack_ch6_init[] = { + /* set pin widget 1Ah (line in) for output */ + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* set pin widget 18h (mic1) for output */ + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* unmute the output for Line In PW */ + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, + /* unmute for Mic1 PW */ + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, + /* for rear channel output using Line In 1 + * set select widget connection (nid = 0x12) - to summer node + * for rear NID = 0x0f...offset 3 in connection list + */ + { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 }, + /* for Mic1 - retask for center/lfe */ + /* set select widget connection (nid = 0x10) - to summer node for + * front CLFE NID = 0x0e...offset 2 in connection list + */ + { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 }, + { } /* end */ +}; + +static struct alc_channel_mode alc880_threestack_modes[2] = { + { 2, alc880_threestack_ch2_init }, + { 6, alc880_threestack_ch6_init }, +}; + + +/* + * channel source setting (6/8 channel selection for 5-stack) + */ + +/* set the path ways for 6 channel output + * need to set the codec line out and mic 1 pin widgets to inputs + */ +static struct hda_verb alc880_fivestack_ch6_init[] = { + /* set pin widget 1Ah (line in) for input */ + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, + /* mute the output for Line In PW */ + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, + { } /* end */ +}; + +/* need to set the codec line out and mic 1 pin widgets to outputs */ +static struct hda_verb alc880_fivestack_ch8_init[] = { + /* set pin widget 1Ah (line in) for output */ + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, + /* unmute the output for Line In PW */ + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, + /* output for surround channel output using Line In 1 */ + /* set select widget connection (nid = 0x12) - to summer node + * for surr_rear NID = 0x0d...offset 1 in connection list + */ + { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 }, + { } /* end */ +}; + +static struct alc_channel_mode alc880_fivestack_modes[2] = { + { 6, alc880_fivestack_ch6_init }, + { 8, alc880_fivestack_ch8_init }, +}; + +/* + * channel source setting for W810 system + * + * W810 has rear IO for: + * Front (DAC 02) + * Surround (DAC 03) + * Center/LFE (DAC 04) + * Digital out (06) + * + * The system also has a pair of internal speakers, and a headphone jack. + * These are both connected to Line2 on the codec, hence to DAC 02. + * + * There is a variable resistor to control the speaker or headphone + * volume. This is a hardware-only device without a software API. + * + * Plugging headphones in will disable the internal speakers. This is + * implemented in hardware, not via the driver using jack sense. In + * a similar fashion, plugging into the rear socket marked "front" will + * disable both the speakers and headphones. + * + * For input, there's a microphone jack, and an "audio in" jack. + * These may not do anything useful with this driver yet, because I + * haven't setup any initialization verbs for these yet... + */ + +static struct alc_channel_mode alc880_w810_modes[1] = { + { 6, NULL } +}; + +/* + */ +static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + + snd_assert(spec->channel_mode, return -ENXIO); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item >= 2) + uinfo->value.enumerated.item = 1; + sprintf(uinfo->value.enumerated.name, "%dch", + spec->channel_mode[uinfo->value.enumerated.item].channels); + return 0; +} + +static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + + snd_assert(spec->channel_mode, return -ENXIO); + ucontrol->value.enumerated.item[0] = + (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1; + return 0; +} + +static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + int mode; + + snd_assert(spec->channel_mode, return -ENXIO); + mode = ucontrol->value.enumerated.item[0] ? 1 : 0; + if (spec->multiout.max_channels == spec->channel_mode[mode].channels && + ! codec->in_resume) + return 0; + + /* change the current channel setting */ + spec->multiout.max_channels = spec->channel_mode[mode].channels; + if (spec->channel_mode[mode].sequence) + snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence); + + return 1; +} + + +/* + */ + +/* 3-stack mode + * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b + * HP=0x19 + */ +static snd_kcontrol_new_t alc880_base_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + * FIXME: the controls appear in the "playback" view! + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Channel Mode", + .info = alc880_ch_mode_info, + .get = alc880_ch_mode_get, + .put = alc880_ch_mode_put, + }, + { } /* end */ +}; + +/* 5-stack mode + * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16 + * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19 + */ +static snd_kcontrol_new_t alc880_five_stack_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + * FIXME: the controls appear in the "playback" view! + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Channel Mode", + .info = alc880_ch_mode_info, + .get = alc880_ch_mode_get, + .put = alc880_ch_mode_put, + }, + { } /* end */ +}; + +static snd_kcontrol_new_t alc880_w810_base_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + * FIXME: the controls appear in the "playback" view! + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 3, + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { } /* end */ +}; + +/* + */ +static int alc_build_controls(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int err; + int i; + + for (i = 0; i < spec->num_mixers; i++) { + err = snd_hda_add_new_ctls(codec, spec->mixers[i]); + if (err < 0) + return err; + } + + if (spec->multiout.dig_out_nid) { + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); + if (err < 0) + return err; + } + if (spec->dig_in_nid) { + err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); + if (err < 0) + return err; + } + return 0; +} + +/* + * initialize the codec volumes, etc + */ + +static struct hda_verb alc880_init_verbs_three_stack[] = { + /* Line In pin widget for input */ + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* CD pin widget for input */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* Mic1 (rear panel) pin widget for input and vref at 80% */ + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* Mic2 (front panel) pin widget for input and vref at 80% */ + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* unmute amp left and right */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + /* set connection select to line in (default select for this ADC) */ + {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, + /* unmute front mixer amp left (volume = 0) */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* unmute rear mixer amp left and right (volume = 0) */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* unmute rear mixer amp left and right (volume = 0) */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + + /* using rear surround as the path for headphone output */ + /* unmute rear surround mixer amp left and right (volume = 0) */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* PASD 3 stack boards use the Mic 2 as the headphone output */ + /* need to program the selector associated with the Mic 2 pin widget to + * surround path (index 0x01) for headphone output */ + {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* need to retask the Mic 2 pin widget to output */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + + /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B) + * to support the input path of analog loopback + * Note: PASD motherboards uses the Line In 2 as the input for front panel + * mic (mic 2) + */ + /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ + /* unmute CD */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, + /* unmute Line In */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, + /* unmute Mic 1 */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + /* unmute Line In 2 (for PASD boards Mic 2) */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, + + /* Unmute input amps for the line out paths to support the output path of + * analog loopback + * the mixers on the output path has 2 inputs, one from the DAC and one + * from the mixer + */ + /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ + /* Unmute Front out path */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Unmute Surround (used as HP) out path */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Unmute C/LFE out path */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */ + /* Unmute rear Surround out path */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + + { } +}; + +static struct hda_verb alc880_init_verbs_five_stack[] = { + /* Line In pin widget for input */ + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* CD pin widget for input */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* Mic1 (rear panel) pin widget for input and vref at 80% */ + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* Mic2 (front panel) pin widget for input and vref at 80% */ + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* unmute amp left and right */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + /* set connection select to line in (default select for this ADC) */ + {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, + /* unmute front mixer amp left and right (volume = 0) */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* five rear and clfe */ + /* unmute rear mixer amp left and right (volume = 0) */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* unmute clfe mixer amp left and right (volume = 0) */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + + /* using rear surround as the path for headphone output */ + /* unmute rear surround mixer amp left and right (volume = 0) */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* PASD 3 stack boards use the Mic 2 as the headphone output */ + /* need to program the selector associated with the Mic 2 pin widget to + * surround path (index 0x01) for headphone output + */ + {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* need to retask the Mic 2 pin widget to output */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + + /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer + * widget(nid=0x0B) to support the input path of analog loopback + */ + /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */ + /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/ + /* unmute CD */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, + /* unmute Line In */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, + /* unmute Mic 1 */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + /* unmute Line In 2 (for PASD boards Mic 2) */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, + + /* Unmute input amps for the line out paths to support the output path of + * analog loopback + * the mixers on the output path has 2 inputs, one from the DAC and + * one from the mixer + */ + /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ + /* Unmute Front out path */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Unmute Surround (used as HP) out path */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Unmute C/LFE out path */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */ + /* Unmute rear Surround out path */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + + { } +}; + +static struct hda_verb alc880_w810_init_verbs[] = { + /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + + /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, + + /* front channel selector/amp: output 0: unmuted, max volume */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + + /* front out pin: muted, (no volume selection) */ + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + + /* front out pin: NOT headphone enable, out enable, vref disabled */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + + + /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + + /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, + + /* surround channel selector/amp: output 0: unmuted, max volume */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + + /* surround out pin: muted, (no volume selection) */ + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + + /* surround out pin: NOT headphone enable, out enable, vref disabled */ + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + + + /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + + /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, + + /* c/lfe channel selector/amp: output 0: unmuted, max volume */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + + /* c/lfe out pin: muted, (no volume selection) */ + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + + /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + + + /* hphone/speaker input selector: front DAC */ + {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, + + /* hphone/speaker out pin: muted, (no volume selection) */ + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + + /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */ + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + + + { } +}; + +static int alc_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + snd_hda_sequence_write(codec, spec->init_verbs); + return 0; +} + +#ifdef CONFIG_PM +/* + * resume + */ +static int alc_resume(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int i; + + alc_init(codec); + for (i = 0; i < spec->num_mixers; i++) { + snd_hda_resume_ctls(codec, spec->mixers[i]); + } + if (spec->multiout.dig_out_nid) + snd_hda_resume_spdif_out(codec); + if (spec->dig_in_nid) + snd_hda_resume_spdif_in(codec); + + return 0; +} +#endif + +/* + * Analog playback callbacks + */ +static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); +} + +static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} + +static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); +} + +/* + * Digital out + */ +static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); +} + +static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); +} + +/* + * Analog capture + */ +static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], + stream_tag, 0, format); + return 0; +} + +static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct alc_spec *spec = codec->spec; + + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); + return 0; +} + + +/* + */ +static struct hda_pcm_stream alc880_pcm_analog_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 8, + .nid = 0x02, /* NID to query formats and rates */ + .ops = { + .open = alc880_playback_pcm_open, + .prepare = alc880_playback_pcm_prepare, + .cleanup = alc880_playback_pcm_cleanup + }, +}; + +static struct hda_pcm_stream alc880_pcm_analog_capture = { + .substreams = 2, + .channels_min = 2, + .channels_max = 2, + .nid = 0x07, /* NID to query formats and rates */ + .ops = { + .prepare = alc880_capture_pcm_prepare, + .cleanup = alc880_capture_pcm_cleanup + }, +}; + +static struct hda_pcm_stream alc880_pcm_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + /* NID is set in alc_build_pcms */ + .ops = { + .open = alc880_dig_playback_pcm_open, + .close = alc880_dig_playback_pcm_close + }, +}; + +static struct hda_pcm_stream alc880_pcm_digital_capture = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + /* NID is set in alc_build_pcms */ +}; + +static int alc_build_pcms(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; + int i; + + codec->num_pcms = 1; + codec->pcm_info = info; + + info->name = spec->stream_name_analog; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); + info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); + + info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; + for (i = 0; i < spec->num_channel_mode; i++) { + if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) { + info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels; + } + } + + if (spec->multiout.dig_out_nid || spec->dig_in_nid) { + codec->num_pcms++; + info++; + info->name = spec->stream_name_digital; + if (spec->multiout.dig_out_nid) { + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; + } + if (spec->dig_in_nid) { + info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture); + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; + } + } + + return 0; +} + +static void alc_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} + +/* + */ +static struct hda_codec_ops alc_patch_ops = { + .build_controls = alc_build_controls, + .build_pcms = alc_build_pcms, + .init = alc_init, + .free = alc_free, +#ifdef CONFIG_PM + .resume = alc_resume, +#endif +}; + +/* + */ + +static struct hda_board_config alc880_cfg_tbl[] = { + /* Back 3 jack, front 2 jack */ + { .modelname = "3stack", .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST }, + { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST }, + { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST }, + { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST }, + { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST }, + { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST }, + { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST }, + { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST }, + + /* Back 3 jack, front 2 jack (Internal add Aux-In) */ + { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST }, + + /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ + { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG }, + + /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ + { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG }, + { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG }, + + /* Back 5 jack, front 2 jack */ + { .modelname = "5stack", .config = ALC880_5ST }, + { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST }, + { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST }, + { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST }, + { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST }, + + /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ + { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG }, + { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG }, + + { .modelname = "w810", .config = ALC880_W810 }, + { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 }, + + {} +}; + +static int patch_alc880(struct hda_codec *codec) +{ + struct alc_spec *spec; + int board_config; + + spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + + board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); + if (board_config < 0) { + snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n"); + board_config = ALC880_MINIMAL; + } + + switch (board_config) { + case ALC880_W810: + spec->mixers[spec->num_mixers] = alc880_w810_base_mixer; + spec->num_mixers++; + break; + case ALC880_5ST: + case ALC880_5ST_DIG: + spec->mixers[spec->num_mixers] = alc880_five_stack_mixer; + spec->num_mixers++; + break; + default: + spec->mixers[spec->num_mixers] = alc880_base_mixer; + spec->num_mixers++; + break; + } + + switch (board_config) { + case ALC880_3ST_DIG: + case ALC880_5ST_DIG: + case ALC880_W810: + spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; + break; + default: + break; + } + + switch (board_config) { + case ALC880_3ST: + case ALC880_3ST_DIG: + case ALC880_5ST: + case ALC880_5ST_DIG: + case ALC880_W810: + spec->front_panel = 1; + break; + default: + break; + } + + switch (board_config) { + case ALC880_5ST: + case ALC880_5ST_DIG: + spec->init_verbs = alc880_init_verbs_five_stack; + spec->channel_mode = alc880_fivestack_modes; + spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes); + break; + case ALC880_W810: + spec->init_verbs = alc880_w810_init_verbs; + spec->channel_mode = alc880_w810_modes; + spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes); + break; + default: + spec->init_verbs = alc880_init_verbs_three_stack; + spec->channel_mode = alc880_threestack_modes; + spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes); + break; + } + + spec->stream_name_analog = "ALC880 Analog"; + spec->stream_analog_playback = &alc880_pcm_analog_playback; + spec->stream_analog_capture = &alc880_pcm_analog_capture; + + spec->stream_name_digital = "ALC880 Digital"; + spec->stream_digital_playback = &alc880_pcm_digital_playback; + spec->stream_digital_capture = &alc880_pcm_digital_capture; + + spec->multiout.max_channels = spec->channel_mode[0].channels; + + switch (board_config) { + case ALC880_W810: + spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids); + spec->multiout.dac_nids = alc880_w810_dac_nids; + // No dedicated headphone socket - it's shared with built-in speakers. + break; + default: + spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids); + spec->multiout.dac_nids = alc880_dac_nids; + spec->multiout.hp_nid = 0x03; /* rear-surround NID */ + break; + } + + spec->input_mux = &alc880_capture_source; + spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); + spec->adc_nids = alc880_adc_nids; + + codec->patch_ops = alc_patch_ops; + + return 0; +} + +/* + * ALC260 support + */ + +/* + * This is just place-holder, so there's something for alc_build_pcms to look + * at when it calculates the maximum number of channels. ALC260 has no mixer + * element which allows changing the channel mode, so the verb list is + * never used. + */ +static struct alc_channel_mode alc260_modes[1] = { + { 2, NULL }, +}; + +snd_kcontrol_new_t alc260_base_mixer[] = { + HDA_CODEC_VOLUME("PCM Playback Volume", 0x08, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x0f, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { } /* end */ +}; + +static struct hda_verb alc260_init_verbs[] = { + /* Line In pin widget for input */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* CD pin widget for input */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* Mic1 (rear panel) pin widget for input and vref at 80% */ + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* Mic2 (front panel) pin widget for input and vref at 80% */ + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* unmute amp left and right */ + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + /* set connection select to line in (default select for this ADC) */ + {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, + /* unmute Line-Out mixer amp left and right (volume = 0) */ + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* unmute HP mixer amp left and right (volume = 0) */ + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ + /* unmute CD */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, + /* unmute Line In */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, + /* unmute Mic */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ + /* Unmute Front out path */ + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Unmute Headphone out path */ + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + { } +}; + +static struct hda_pcm_stream alc260_pcm_analog_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = 0x2, +}; + +static struct hda_pcm_stream alc260_pcm_analog_capture = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = 0x4, +}; + +static int patch_alc260(struct hda_codec *codec) +{ + struct alc_spec *spec; + + spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + + spec->mixers[spec->num_mixers] = alc260_base_mixer; + spec->num_mixers++; + + spec->init_verbs = alc260_init_verbs; + spec->channel_mode = alc260_modes; + spec->num_channel_mode = ARRAY_SIZE(alc260_modes); + + spec->stream_name_analog = "ALC260 Analog"; + spec->stream_analog_playback = &alc260_pcm_analog_playback; + spec->stream_analog_capture = &alc260_pcm_analog_capture; + + spec->multiout.max_channels = spec->channel_mode[0].channels; + spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids); + spec->multiout.dac_nids = alc260_dac_nids; + + spec->input_mux = &alc260_capture_source; + spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); + spec->adc_nids = alc260_adc_nids; + + codec->patch_ops = alc_patch_ops; + + return 0; +} + +/* + * ALC882 support + * + * ALC882 is almost identical with ALC880 but has cleaner and more flexible + * configuration. Each pin widget can choose any input DACs and a mixer. + * Each ADC is connected from a mixer of all inputs. This makes possible + * 6-channel independent captures. + * + * In addition, an independent DAC for the multi-playback (not used in this + * driver yet). + */ + +static struct alc_channel_mode alc882_ch_modes[1] = { + { 8, NULL } +}; + +static hda_nid_t alc882_dac_nids[4] = { + /* front, rear, clfe, rear_surr */ + 0x02, 0x03, 0x04, 0x05 +}; + +static hda_nid_t alc882_adc_nids[3] = { + /* ADC0-2 */ + 0x07, 0x08, 0x09, +}; + +/* input MUX */ +/* FIXME: should be a matrix-type input source selection */ + +static struct hda_input_mux alc882_capture_source = { + .num_items = 4, + .items = { + { "Mic", 0x0 }, + { "Front Mic", 0x1 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + +#define alc882_mux_enum_info alc_mux_enum_info +#define alc882_mux_enum_get alc_mux_enum_get + +static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + const struct hda_input_mux *imux = spec->input_mux; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; + hda_nid_t nid = capture_mixers[adc_idx]; + unsigned int *cur_val = &spec->cur_mux[adc_idx]; + unsigned int i, idx; + + idx = ucontrol->value.enumerated.item[0]; + if (idx >= imux->num_items) + idx = imux->num_items - 1; + if (*cur_val == idx && ! codec->in_resume) + return 0; + for (i = 0; i < imux->num_items; i++) { + unsigned int v = (i == idx) ? 0x7000 : 0x7080; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + v | (imux->items[i].index << 8)); + } + *cur_val = idx; + return 1; +} + +/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 + * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b + */ +static snd_kcontrol_new_t alc882_base_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 3, + .info = alc882_mux_enum_info, + .get = alc882_mux_enum_get, + .put = alc882_mux_enum_put, + }, + { } /* end */ +}; + +static struct hda_verb alc882_init_verbs[] = { + /* Front mixer: unmute input/output amp left and right (volume = 0) */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + /* Rear mixer */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + /* CLFE mixer */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + /* Side mixer */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + + /* Front Pin: to output mode */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + /* Front Pin: mute amp left and right (no volume) */ + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* select Front mixer (0x0c, index 0) */ + {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* Rear Pin */ + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + /* Rear Pin: mute amp left and right (no volume) */ + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* select Rear mixer (0x0d, index 1) */ + {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, + /* CLFE Pin */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + /* CLFE Pin: mute amp left and right (no volume) */ + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* select CLFE mixer (0x0e, index 2) */ + {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, + /* Side Pin */ + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + /* Side Pin: mute amp left and right (no volume) */ + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* select Side mixer (0x0f, index 3) */ + {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, + /* Headphone Pin */ + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + /* Headphone Pin: mute amp left and right (no volume) */ + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, + /* select Front mixer (0x0c, index 0) */ + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* Mic (rear) pin widget for input and vref at 80% */ + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* Front Mic pin widget for input and vref at 80% */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + /* Line In pin widget for input */ + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + /* CD pin widget for input */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + + /* FIXME: use matrix-type input source selection */ + /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ + /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, + /* Input mixer2 */ + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, + /* Input mixer3 */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, + /* ADC1: unmute amp left and right */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + /* ADC2: unmute amp left and right */ + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + /* ADC3: unmute amp left and right */ + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, + + /* Unmute front loopback */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Unmute rear loopback */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + /* Mute CLFE loopback */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, + /* Unmute side loopback */ + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, + + { } +}; + +static int patch_alc882(struct hda_codec *codec) +{ + struct alc_spec *spec; + + spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + + spec->mixers[spec->num_mixers] = alc882_base_mixer; + spec->num_mixers++; + + spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; + spec->dig_in_nid = ALC880_DIGIN_NID; + spec->front_panel = 1; + spec->init_verbs = alc882_init_verbs; + spec->channel_mode = alc882_ch_modes; + spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); + + spec->stream_name_analog = "ALC882 Analog"; + spec->stream_analog_playback = &alc880_pcm_analog_playback; + spec->stream_analog_capture = &alc880_pcm_analog_capture; + + spec->stream_name_digital = "ALC882 Digital"; + spec->stream_digital_playback = &alc880_pcm_digital_playback; + spec->stream_digital_capture = &alc880_pcm_digital_capture; + + spec->multiout.max_channels = spec->channel_mode[0].channels; + spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids); + spec->multiout.dac_nids = alc882_dac_nids; + + spec->input_mux = &alc882_capture_source; + spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); + spec->adc_nids = alc882_adc_nids; + + codec->patch_ops = alc_patch_ops; + + return 0; +} + +/* + * patch entries + */ +struct hda_codec_preset snd_hda_preset_realtek[] = { + { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, + { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, + { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, + {} /* terminator */ +}; diff -Nru a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile --- a/sound/pci/ice1712/Makefile 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/Makefile 2005-03-03 21:43:47 -08: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 vt1720_mobo.o pontis.o prodigy192.o +snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o # Toplevel Module Dependency obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o diff -Nru a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c --- a/sound/pci/ice1712/ak4xxx.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/ice1712/ak4xxx.c 2005-03-03 21:43:46 -08:00 @@ -126,12 +126,16 @@ { struct snd_ak4xxx_private *priv; - priv = kmalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; + if (_priv != NULL) { + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + *priv = *_priv; + } else { + priv = NULL; + } *ak = *temp; ak->card = ice->card; - *priv = *_priv; ak->private_value[0] = (unsigned long)priv; ak->private_data[0] = ice; if (ak->ops.lock == NULL) diff -Nru a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h --- a/sound/pci/ice1712/envy24ht.h 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/envy24ht.h 2005-03-03 21:43:47 -08:00 @@ -106,7 +106,7 @@ #define VT1724_REG_I2C_BYTE_ADDR 0x11 /* byte */ #define VT1724_REG_I2C_DATA 0x12 /* byte */ #define VT1724_REG_I2C_CTRL 0x13 /* byte */ -#define VT1724_I2C_EEPROM 0x80 /* EEPROM exists */ +#define VT1724_I2C_EEPROM 0x80 /* 1 = EEPROM exists */ #define VT1724_I2C_BUSY 0x01 /* busy bit */ #define VT1724_REG_GPIO_DATA 0x14 /* word */ diff -Nru a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c --- a/sound/pci/ice1712/ice1712.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/ice1712.c 2005-03-03 21:43:47 -08:00 @@ -1014,21 +1014,9 @@ static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int force) { unsigned long flags; - unsigned char val; + unsigned char val, old; unsigned int i; - spin_lock_irqsave(&ice->reg_lock, flags); - if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| - ICE1712_PLAYBACK_PAUSE| - ICE1712_PLAYBACK_START)) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - if (!force && is_pro_rate_locked(ice)) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - switch (rate) { case 8000: val = 6; break; case 9600: val = 3; break; @@ -1049,8 +1037,22 @@ rate = 48000; break; } - outb(val, ICEMT(ice, RATE)); + spin_lock_irqsave(&ice->reg_lock, flags); + if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| + ICE1712_PLAYBACK_PAUSE| + ICE1712_PLAYBACK_START)) { + __out: + spin_unlock_irqrestore(&ice->reg_lock, flags); + return; + } + if (!force && is_pro_rate_locked(ice)) + goto __out; + + old = inb(ICEMT(ice, RATE)); + if (!force && old == val) + goto __out; + outb(val, ICEMT(ice, RATE)); spin_unlock_irqrestore(&ice->reg_lock, flags); if (ice->gpio.set_pro_rate) @@ -2405,6 +2407,7 @@ udelay(200); snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0); } + snd_ice1712_set_pro_rate(ice, 48000, 1); return 0; } @@ -2545,6 +2548,7 @@ ice->cs8427_timeout = cs8427_timeout; spin_lock_init(&ice->reg_lock); init_MUTEX(&ice->gpio_mutex); + init_MUTEX(&ice->i2c_mutex); init_MUTEX(&ice->open_mutex); ice->gpio.set_mask = snd_ice1712_set_gpio_mask; ice->gpio.set_dir = snd_ice1712_set_gpio_dir; diff -Nru a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h --- a/sound/pci/ice1712/ice1712.h 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/ice1712/ice1712.h 2005-03-03 21:43:46 -08:00 @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -340,6 +341,7 @@ akm4xxx_t *akm; struct snd_ice1712_spdif spdif; + struct semaphore i2c_mutex; /* I2C mutex for ICE1724 registers */ snd_i2c_bus_t *i2c; /* I2C bus */ snd_i2c_device_t *cs8427; /* CS8427 I2C device */ unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */ @@ -355,12 +357,13 @@ unsigned int (*get_data)(ice1712_t *ice); /* misc operators - move to another place? */ void (*set_pro_rate)(ice1712_t *ice, unsigned int rate); + void (*i2s_mclk_changed)(ice1712_t *ice); } gpio; struct semaphore gpio_mutex; /* other board-specific data */ union { - /* additional i2c devices for EWS boards*/ + /* additional i2c devices for EWS boards */ snd_i2c_device_t *i2cdevs[3]; /* AC97 register cache for Aureon */ struct aureon_spec { @@ -375,6 +378,10 @@ unsigned int config; unsigned short boxconfig[4]; } hoontech; + struct { + ak4114_t *ak4114; + unsigned int analog: 1; + } juli; } spec; }; @@ -477,7 +484,7 @@ char *driver; int (*chip_init)(ice1712_t *); int (*build_controls)(ice1712_t *); - int no_mpu401: 1; + unsigned int no_mpu401: 1; unsigned int eeprom_size; unsigned char *eeprom_data; }; diff -Nru a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c --- a/sound/pci/ice1712/ice1724.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/ice1724.c 2005-03-03 21:43:47 -08:00 @@ -47,6 +47,8 @@ #include "vt1720_mobo.h" #include "pontis.h" #include "prodigy192.h" +#include "juli.h" +#include "phase.h" MODULE_AUTHOR("Jaroslav Kysela "); @@ -59,6 +61,8 @@ VT1720_MOBO_DEVICE_DESC PONTIS_DEVICE_DESC PRODIGY192_DEVICE_DESC + JULI_DEVICE_DESC + PHASE_DEVICE_DESC "{VIA,VT1720}," "{VIA,VT1724}," "{ICEnsemble,Generic ICE1724}," @@ -401,23 +405,11 @@ { unsigned long flags; unsigned char val, old; - unsigned int i; + unsigned int i, mclk_change; if (rate > get_max_rate(ice)) return; - spin_lock_irqsave(&ice->reg_lock, flags); - if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || - (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { - /* running? we cannot change the rate now... */ - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - if (!force && is_pro_rate_locked(ice)) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - switch (rate) { case 8000: val = 6; break; case 9600: val = 3; break; @@ -439,8 +431,21 @@ val = 0; break; } + + spin_lock_irqsave(&ice->reg_lock, flags); + if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || + (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { + /* running? we cannot change the rate now... */ + spin_unlock_irqrestore(&ice->reg_lock, flags); + return; + } + if (!force && is_pro_rate_locked(ice)) { + spin_unlock_irqrestore(&ice->reg_lock, flags); + return; + } + old = inb(ICEMT1724(ice, RATE)); - if (old != val) + if (force || old != val) outb(val, ICEMT1724(ice, RATE)); else if (rate == ice->cur_rate) { spin_unlock_irqrestore(&ice->reg_lock, flags); @@ -450,6 +455,7 @@ ice->cur_rate = rate; /* check MT02 */ + mclk_change = 0; if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { val = old = inb(ICEMT1724(ice, I2S_FORMAT)); if (rate > 96000) @@ -458,25 +464,23 @@ val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */ if (val != old) { outb(val, ICEMT1724(ice, I2S_FORMAT)); - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_REVOLUTION71) { - /* FIXME: is this revo only? */ - /* assert PRST# to converters; MT05 bit 7 */ - outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); - spin_unlock_irqrestore(&ice->reg_lock, flags); - mdelay(5); - spin_lock_irqsave(&ice->reg_lock, flags); - /* deassert PRST# */ - outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); - } + mclk_change = 1; } } spin_unlock_irqrestore(&ice->reg_lock, flags); + if (mclk_change && ice->gpio.i2s_mclk_changed) + ice->gpio.i2s_mclk_changed(ice); + if (ice->gpio.set_pro_rate) + ice->gpio.set_pro_rate(ice, rate); + /* set up codecs */ for (i = 0; i < ice->akm_codecs; i++) { if (ice->akm[i].ops.set_rate_val) ice->akm[i].ops.set_rate_val(&ice->akm[i], rate); } + if (ice->spdif.ops.setup_rate) + ice->spdif.ops.setup_rate(ice, rate); } static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream, @@ -1866,6 +1870,8 @@ snd_vt1720_mobo_cards, snd_vt1720_pontis_cards, snd_vt1724_prodigy192_cards, + snd_vt1724_juli_cards, + snd_vt1724_phase_cards, NULL, }; @@ -1878,23 +1884,34 @@ int t = 0x10000; while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--) ; + if (t == -1) + printk(KERN_ERR "ice1724: i2c busy timeout\n"); } unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr) { + unsigned char val; + + down(&ice->i2c_mutex); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); - return inb(ICEREG1724(ice, I2C_DATA)); + val = inb(ICEREG1724(ice, I2C_DATA)); + up(&ice->i2c_mutex); + //printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); + return val; } void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data) { + down(&ice->i2c_mutex); wait_i2c_busy(ice); + //printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(data, ICEREG1724(ice, I2C_DATA)); outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); + up(&ice->i2c_mutex); } static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname) @@ -1906,7 +1923,8 @@ if (! modelname || ! *modelname) { ice->eeprom.subvendor = 0; if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) != 0) - ice->eeprom.subvendor = (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) | + ice->eeprom.subvendor = + (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) | (snd_vt1724_read_i2c(ice, dev, 0x01) << 8) | (snd_vt1724_read_i2c(ice, dev, 0x02) << 16) | (snd_vt1724_read_i2c(ice, dev, 0x03) << 24); @@ -2114,6 +2132,7 @@ spin_lock_init(&ice->reg_lock); init_MUTEX(&ice->gpio_mutex); init_MUTEX(&ice->open_mutex); + init_MUTEX(&ice->i2c_mutex); ice->gpio.set_mask = snd_vt1724_set_gpio_mask; ice->gpio.set_dir = snd_vt1724_set_gpio_dir; ice->gpio.set_data = snd_vt1724_set_gpio_data; diff -Nru a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/ice1712/juli.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,230 @@ +/* + * ALSA driver for ICEnsemble VT1724 (Envy24HT) + * + * Lowlevel functions for ESI Juli@ cards + * + * Copyright (c) 2004 Jaroslav Kysela + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "ice1712.h" +#include "envy24ht.h" +#include "juli.h" + +/* + * chip addresses on I2C bus + */ +#define AK4114_ADDR 0x20 /* S/PDIF receiver */ +#define AK4358_ADDR 0x22 /* DAC */ + +/* + * GPIO pins + */ +#define GPIO_FREQ_MASK (3<<0) +#define GPIO_FREQ_32KHZ (0<<0) +#define GPIO_FREQ_44KHZ (1<<0) +#define GPIO_FREQ_48KHZ (2<<0) +#define GPIO_MULTI_MASK (3<<2) +#define GPIO_MULTI_4X (0<<2) +#define GPIO_MULTI_2X (1<<2) +#define GPIO_MULTI_1X (2<<2) /* also external */ +#define GPIO_MULTI_HALF (3<<2) +#define GPIO_INTERNAL_CLOCK (1<<4) +#define GPIO_ANALOG_PRESENT (1<<5) /* RO only: 0 = present */ +#define GPIO_RXMCLK_SEL (1<<7) /* must be 0 */ +#define GPIO_AK5385A_CKS0 (1<<8) +#define GPIO_AK5385A_DFS0 (1<<9) /* swapped with DFS1 according doc? */ +#define GPIO_AK5385A_DFS1 (1<<10) +#define GPIO_DIGOUT_MONITOR (1<<11) /* 1 = active */ +#define GPIO_DIGIN_MONITOR (1<<12) /* 1 = active */ +#define GPIO_ANAIN_MONITOR (1<<13) /* 1 = active */ +#define GPIO_AK5385A_MCLK (1<<14) /* must be 0 */ +#define GPIO_MUTE_CONTROL (1<<15) /* 0 = off, 1 = on */ + +static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val) +{ + snd_vt1724_write_i2c((ice1712_t *)private_data, AK4114_ADDR, reg, val); +} + +static unsigned char juli_ak4114_read(void *private_data, unsigned char reg) +{ + return snd_vt1724_read_i2c((ice1712_t *)private_data, AK4114_ADDR, reg); +} + +/* + * AK4358 section + */ + +static void juli_akm_lock(akm4xxx_t *ak, int chip) +{ +} + +static void juli_akm_unlock(akm4xxx_t *ak, int chip) +{ +} + +static void juli_akm_write(akm4xxx_t *ak, int chip, + unsigned char addr, unsigned char data) +{ + ice1712_t *ice = ak->private_data[0]; + + snd_assert(chip == 0, return); + snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data); +} + +/* + * change the rate of envy24HT, AK4358 + */ +static void juli_akm_set_rate_val(akm4xxx_t *ak, unsigned int rate) +{ + unsigned char old, tmp, dfs; + + if (rate == 0) /* no hint - S/PDIF input is master, simply return */ + return; + + /* adjust DFS on codecs */ + if (rate > 96000) + dfs = 2; + else if (rate > 48000) + dfs = 1; + else + dfs = 0; + + tmp = snd_akm4xxx_get(ak, 0, 2); + old = (tmp >> 4) & 0x03; + if (old == dfs) + return; + /* reset DFS */ + snd_akm4xxx_reset(ak, 1); + tmp = snd_akm4xxx_get(ak, 0, 2); + tmp &= ~(0x03 << 4); + tmp |= dfs << 4; + snd_akm4xxx_set(ak, 0, 2, tmp); + snd_akm4xxx_reset(ak, 0); +} + +static akm4xxx_t akm_juli_dac __devinitdata = { + .type = SND_AK4358, + .num_dacs = 2, + .ops = { + .lock = juli_akm_lock, + .unlock = juli_akm_unlock, + .write = juli_akm_write, + .set_rate_val = juli_akm_set_rate_val + } +}; + +static int __devinit juli_add_controls(ice1712_t *ice) +{ + return snd_ice1712_akm4xxx_build_controls(ice); +} + +/* + * initialize the chip + */ +static int __devinit juli_init(ice1712_t *ice) +{ + static unsigned char ak4114_init_vals[] = { + /* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, + /* AK4114_REQ_FORMAT */ AK4114_DIF_I24I2S, + /* AK4114_REG_IO0 */ AK4114_TX1E, + /* AK4114_REG_IO1 */ AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1), + /* AK4114_REG_INT0_MASK */ 0, + /* AK4114_REG_INT1_MASK */ 0 + }; + static unsigned char ak4114_init_txcsb[] = { + 0x41, 0x02, 0x2c, 0x00, 0x00 + }; + int err; + akm4xxx_t *ak; + +#if 0 + for (err = 0; err < 0x20; err++) + juli_ak4114_read(ice, err); + juli_ak4114_write(ice, 0, 0x0f); + juli_ak4114_read(ice, 0); + juli_ak4114_read(ice, 1); +#endif + err = snd_ak4114_create(ice->card, + juli_ak4114_read, + juli_ak4114_write, + ak4114_init_vals, ak4114_init_txcsb, + ice, &ice->spec.juli.ak4114); + if (err < 0) + return err; + + ice->spec.juli.analog = ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT; + + if (ice->spec.juli.analog) { + printk(KERN_INFO "juli@: analog I/O detected\n"); + ice->num_total_dacs = 2; + ice->num_total_adcs = 2; + + ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL); + if (! ak) + return -ENOMEM; + ice->akm_codecs = 1; + if ((err = snd_ice1712_akm4xxx_init(ak, &akm_juli_dac, NULL, ice)) < 0) + return err; + } + + return 0; +} + + +/* + * Juli@ boards don't provide the EEPROM data except for the vendor IDs. + * hence the driver needs to sets up it properly. + */ + +static unsigned char juli_eeprom[] __devinitdata = { + 0x20, /* SYSCONF: clock 512, mpu401, 1xADC, 1xDACs */ + 0x80, /* ACLINK: I2S */ + 0xf8, /* I2S: vol, 96k, 24bit, 192k */ + 0xc3, /* SPDIF: out-en, out-int, spdif-in */ + 0x9f, /* GPIO_DIR */ + 0xff, /* GPIO_DIR1 */ + 0x7f, /* GPIO_DIR2 */ + 0x9f, /* GPIO_MASK */ + 0xff, /* GPIO_MASK1 */ + 0x7f, /* GPIO_MASK2 */ + 0x16, /* GPIO_STATE: internal clock, multiple 1x, 48kHz */ + 0x80, /* GPIO_STATE1: mute */ + 0x00, /* GPIO_STATE2 */ +}; + +/* entry point */ +struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = { + { + .subvendor = VT1724_SUBDEVICE_JULI, + .name = "ESI Juli@", + .model = "juli", + .chip_init = juli_init, + .build_controls = juli_add_controls, + .eeprom_size = sizeof(juli_eeprom), + .eeprom_data = juli_eeprom, + }, + { } /* terminator */ +}; diff -Nru a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/ice1712/juli.h 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,10 @@ +#ifndef __SOUND_JULI_H +#define __SOUND_JULI_H + +#define JULI_DEVICE_DESC "{ESI,Juli@}," + +#define VT1724_SUBDEVICE_JULI 0x31305345 /* Juli@ */ + +extern struct snd_ice1712_card_info snd_vt1724_juli_cards[]; + +#endif /* __SOUND_JULI_H */ diff -Nru a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/ice1712/phase.c 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,138 @@ +/* + * ALSA driver for ICEnsemble ICE1724 (Envy24) + * + * Lowlevel functions for Terratec PHASE 22 + * + * Copyright (c) 2005 Misha Zhilin + * + * 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 + * + */ + +/* PHASE 22 overview: + * Audio controller: VIA Envy24HT-S (slightly trimmed down version of Envy24HT) + * Analog chip: AK4524 (partially via Philip's 74HCT125) + * Digital receiver: CS8414-CS (not supported in this release) + * + * Envy connects to AK4524 + * - CS directly from GPIO 10 + * - CCLK via 74HCT125's gate #4 from GPIO 4 + * - CDTI via 74HCT125's gate #2 from GPIO 5 + * CDTI may be completely blocked by 74HCT125's gate #1 controlled by GPIO 3 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ice1712.h" +#include "envy24ht.h" +#include "phase.h" + +static akm4xxx_t akm_phase22 __devinitdata = { + .type = SND_AK4524, + .num_dacs = 2, + .num_adcs = 2, +}; + +static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = { + .caddr = 2, + .cif = 1, + .data_mask = 1 << 4, + .clk_mask = 1 << 5, + .cs_mask = 1 << 10, + .cs_addr = 1 << 10, + .cs_none = 0, + .add_flags = 1 << 3, + .mask_flags = 0, +}; + +static int __devinit phase22_init(ice1712_t *ice) +{ + akm4xxx_t *ak; + int err; + + // Configure DAC/ADC description for generic part of ice1724 + switch (ice->eeprom.subvendor) { + case VT1724_SUBDEVICE_PHASE22: + ice->num_total_dacs = 2; + ice->num_total_adcs = 2; + ice->vt1720 = 1; // Envy24HT-S have 16 bit wide GPIO + break; + default: + snd_BUG(); + return -EINVAL; + } + + // Initialize analog chips + ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL); + if (! ak) + return -ENOMEM; + ice->akm_codecs = 1; + switch (ice->eeprom.subvendor) { + case VT1724_SUBDEVICE_PHASE22: + if ((err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, &akm_phase22_priv, ice)) < 0) + return err; + break; + } + + return 0; +} + +static int __devinit phase22_add_controls(ice1712_t *ice) +{ + int err = 0; + + switch (ice->eeprom.subvendor) { + case VT1724_SUBDEVICE_PHASE22: + err = snd_ice1712_akm4xxx_build_controls(ice); + if (err < 0) + return err; + } + return 0; +} + +static unsigned char phase22_eeprom[] __devinitdata = { + 0x00, /* SYSCONF: 1xADC, 1xDACs */ + 0x80, /* ACLINK: I2S */ + 0xf8, /* I2S: vol, 96k, 24bit*/ + 0xc3, /* SPDIF: out-en, out-int, spdif-in */ + 0xFF, /* GPIO_DIR */ + 0xFF, /* GPIO_DIR1 */ + 0xFF, /* GPIO_DIR2 */ + 0x00, /* GPIO_MASK */ + 0x00, /* GPIO_MASK1 */ + 0x00, /* GPIO_MASK2 */ + 0x00, /* GPIO_STATE: */ + 0x00, /* GPIO_STATE1: */ + 0x00, /* GPIO_STATE2 */ +}; + +struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { + { + .subvendor = VT1724_SUBDEVICE_PHASE22, + .name = "Terratec PHASE 22", + .model = "phase22", + .chip_init = phase22_init, + .build_controls = phase22_add_controls, + .eeprom_size = sizeof(phase22_eeprom), + .eeprom_data = phase22_eeprom, + }, + { } /* terminator */ +}; diff -Nru a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/sound/pci/ice1712/phase.h 2005-03-03 21:43:47 -08:00 @@ -0,0 +1,34 @@ +#ifndef __SOUND_PHASE_H +#define __SOUND_PHASE_H + +/* + * ALSA driver for ICEnsemble ICE1712 (Envy24) + * + * Lowlevel functions for Terratec PHASE 22 + * + * Copyright (c) 2005 Misha Zhilin + * + * 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 PHASE_DEVICE_DESC "{Terratec,Phase 22}," + +#define VT1724_SUBDEVICE_PHASE22 0x3b155011 + +/* entry point */ +extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; + +#endif /* __SOUND_PHASE */ diff -Nru a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c --- a/sound/pci/ice1712/prodigy192.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/prodigy192.c 2005-03-03 21:43:47 -08:00 @@ -36,12 +36,12 @@ #include "prodigy192.h" #include "stac946x.h" -static void stac9460_put(ice1712_t *ice, int reg, unsigned char val) +static inline void stac9460_put(ice1712_t *ice, int reg, unsigned char val) { snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val); } -static unsigned char stac9460_get(ice1712_t *ice, int reg) +static inline unsigned char stac9460_get(ice1712_t *ice, int reg) { return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg); } diff -Nru a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c --- a/sound/pci/ice1712/revo.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/revo.c 2005-03-03 21:43:47 -08:00 @@ -33,6 +33,15 @@ #include "envy24ht.h" #include "revo.h" +static void revo_i2s_mclk_changed(ice1712_t *ice) +{ + /* assert PRST# to converters; MT05 bit 7 */ + outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); + mdelay(5); + /* deassert PRST# */ + outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); +} + /* * change the rate of envy24HT, AK4355 and AK4381 */ @@ -134,6 +143,8 @@ snd_BUG(); return -EINVAL; } + + ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed; /* second stage of initialization, analog parts and others */ ak = ice->akm = kcalloc(2, sizeof(akm4xxx_t), GFP_KERNEL); diff -Nru a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c --- a/sound/pci/ice1712/vt1720_mobo.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/ice1712/vt1720_mobo.c 2005-03-03 21:43:46 -08:00 @@ -101,6 +101,15 @@ .eeprom_size = sizeof(k8x800_eeprom), .eeprom_data = k8x800_eeprom, }, + { + .subvendor = VT1720_SUBDEVICE_9CJS, + .name = "Chaintech 9CJS", + /* 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 --- a/sound/pci/ice1712/vt1720_mobo.h 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ice1712/vt1720_mobo.h 2005-03-03 21:43:47 -08:00 @@ -26,11 +26,13 @@ #define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\ "{Chaintech,ZNF3-150},"\ - "{Chaintech,ZNF3-250}," + "{Chaintech,ZNF3-250},"\ + "{Chaintech,9CJS}," #define VT1720_SUBDEVICE_K8X800 0xf217052c #define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6 #define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6 +#define VT1720_SUBDEVICE_9CJS 0x0f272327 extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c --- a/sound/pci/intel8x0.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/intel8x0.c 2005-03-03 21:43:47 -08:00 @@ -118,8 +118,8 @@ #ifndef PCI_DEVICE_ID_INTEL_ESB_5 #define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 #endif -#ifndef PCI_DEVICE_ID_INTEL_ICH6_3 -#define PCI_DEVICE_ID_INTEL_ICH6_3 0x266e +#ifndef PCI_DEVICE_ID_INTEL_ICH6_18 +#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e #endif #ifndef PCI_DEVICE_ID_INTEL_ICH7_20 #define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de @@ -1059,7 +1059,7 @@ intel8x0_t *chip = snd_pcm_substream_chip(substream); ichdev_t *ichdev = get_ichdev(substream); size_t ptr1, ptr; - int civ, timeout = 10; + int civ, timeout = 100; unsigned int position; spin_lock(&chip->reg_lock); @@ -1067,8 +1067,10 @@ 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 (ptr1 == 0) { + udelay(10); + continue; + } if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break; @@ -1761,6 +1763,12 @@ }, { .vendor = 0x1028, + .device = 0x012c, + .name = "Dell Precision 650", /* AD1981A */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1028, .device = 0x012d, .name = "Dell Precision 450", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY @@ -1772,6 +1780,12 @@ .type = AC97_TUNE_HP_ONLY }, { + .vendor = 0x1028, + .device = 0x0163, + .name = "Dell Unknown", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { .vendor = 0x103c, .device = 0x006d, .name = "HP zv5000", @@ -1838,6 +1852,12 @@ .type = AC97_TUNE_HP_ONLY }, { + .vendor = 0x10cf, + .device = 0x1253, + .name = "Fujitsu S6210", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { .vendor = 0x10f1, .device = 0x2665, .name = "Fujitsu-Siemens Celsius", /* AD1981? */ @@ -2320,7 +2340,7 @@ /* * power management */ -static int intel8x0_suspend(snd_card_t *card, unsigned int state) +static int intel8x0_suspend(snd_card_t *card, pm_message_t state) { intel8x0_t *chip = card->pm_private_data; int i; @@ -2345,7 +2365,7 @@ return 0; } -static int intel8x0_resume(snd_card_t *card, unsigned int state) +static int intel8x0_resume(snd_card_t *card) { intel8x0_t *chip = card->pm_private_data; int i; @@ -2713,7 +2733,7 @@ { PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" }, { PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" }, { PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" }, - { PCI_DEVICE_ID_INTEL_ICH6_3, "Intel ICH6" }, + { PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" }, { PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" }, { PCI_DEVICE_ID_SI_7012, "SiS SI7012" }, { PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" }, diff -Nru a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c --- a/sound/pci/intel8x0m.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/intel8x0m.c 2005-03-03 21:43:47 -08:00 @@ -35,6 +35,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Jaroslav Kysela "); @@ -54,7 +55,7 @@ "{NVidia,NForce3 Modem}," "{AMD,AMD768}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; @@ -247,7 +248,7 @@ snd_pcm_t *pcm[2]; ichdev_t ichd[2]; - int in_ac97_init: 1; + unsigned int in_ac97_init: 1; ac97_bus_t *ac97_bus; ac97_t *ac97; @@ -281,9 +282,60 @@ #endif { 0, } }; +static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol); +static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol); +static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo); + +#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff)) +#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff) +#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff) + +static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = { + { .name = "Off-hook Switch", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_intel8x0m_switch_default_info, + .get = snd_intel8x0m_switch_default_get, + .put = snd_intel8x0m_switch_default_put, + .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH) + } +}; MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids); +static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + unsigned short mask = PRIVATE_VALUE_MASK(kcontrol); + unsigned short reg = PRIVATE_VALUE_REG(kcontrol); + intel8x0_t *chip = snd_kcontrol_chip(kcontrol); + unsigned int status; + status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0; + ucontrol->value.integer.value[0] = status; + return 0; +} +static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + unsigned short mask = PRIVATE_VALUE_MASK(kcontrol); + unsigned short reg = PRIVATE_VALUE_REG(kcontrol); + intel8x0_t *chip = snd_kcontrol_chip(kcontrol); + unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask; + return snd_ac97_update_bits(chip->ac97, reg, + mask, new_status); +} /* * Lowlevel I/O - busmaster */ @@ -638,17 +690,12 @@ static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd) { - ichdev_t *ichdev = get_ichdev(substream); /* hook off/on on start/stop */ - /* TODO: move it to ac97 controls */ + /* Moved this to mixer control */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS, - AC97_GPIO_LINE1_OH, AC97_GPIO_LINE1_OH); break; case SNDRV_PCM_TRIGGER_STOP: - snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS, - AC97_GPIO_LINE1_OH, ~AC97_GPIO_LINE1_OH); break; default: return -EINVAL; @@ -890,6 +937,7 @@ ac97_t *x97; int err; unsigned int glob_sta = 0; + unsigned int idx; static ac97_bus_ops_t ops = { .write = snd_intel8x0_codec_write, .read = snd_intel8x0_codec_read, @@ -921,10 +969,14 @@ return err; } chip->ac97 = x97; - if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97 ) { + if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97) { chip->ichd[ICHD_MDMIN].ac97 = x97; chip->ichd[ICHD_MDMOUT].ac97 = x97; } + for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) { + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0) + goto __err; + } chip->in_ac97_init = 0; return 0; @@ -1078,7 +1130,7 @@ /* * power management */ -static int intel8x0m_suspend(snd_card_t *card, unsigned int state) +static int intel8x0m_suspend(snd_card_t *card, pm_message_t state) { intel8x0_t *chip = card->pm_private_data; int i; @@ -1091,7 +1143,7 @@ return 0; } -static int intel8x0m_resume(snd_card_t *card, unsigned int state) +static int intel8x0m_resume(snd_card_t *card) { intel8x0_t *chip = card->pm_private_data; pci_enable_device(chip->pci); diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c --- a/sound/pci/korg1212/korg1212.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/korg1212/korg1212.c 2005-03-03 21:43:46 -08:00 @@ -51,7 +51,7 @@ //#define K1212_LARGEALLOC 1 // ---------------------------------------------------------------------------- -// the following enum defines the valid states of the Korg 1212 I/O card. +// Valid states of the Korg 1212 I/O card. // ---------------------------------------------------------------------------- typedef enum { K1212_STATE_NONEXISTENT, // there is no card here @@ -85,6 +85,8 @@ K1212_DB_ConfigureMiscMemory = 6, // tells card where other buffers are. K1212_DB_TriggerFromAdat = 7, // tells card to trigger from Adat at a specific // timecode value. + K1212_DB_DMAERROR = 0x80, // DMA Error - the PCI bus is congestioned. + K1212_DB_CARDSTOPPED = 0x81, // Card has stopped by user request. K1212_DB_RebootCard = 0xA0, // instructs the card to reboot. K1212_DB_BootFromDSPPage4 = 0xA4, // instructs the card to boot from the DSP microcode // on page 4 (local page to card). @@ -93,11 +95,9 @@ K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware. } korg1212_dbcnst_t; -#define K1212_ISRCODE_DMAERROR 0x80 -#define K1212_ISRCODE_CARDSTOPPED 0x81 // ---------------------------------------------------------------------------- -// The following enumeration defines return codes for DeviceIoControl() calls +// The following enumeration defines return codes // to the Korg 1212 I/O driver. // ---------------------------------------------------------------------------- typedef enum { @@ -116,11 +116,6 @@ K1212_CMDRET_NoAckFromCard, // the card never acknowledged a command K1212_CMDRET_BadParams, // bad parameters were provided by the caller - // -------------------------------------------------------------- - // the following return errors are specific to the wave device - // driver interface. These will not be encountered by users of - // the 32 bit DIOC interface (a.k.a. custom or native API). - // -------------------------------------------------------------- K1212_CMDRET_BadDevice, // the specified wave device was out of range K1212_CMDRET_BadFormat // the specified wave format is unsupported } snd_korg1212rc; @@ -400,9 +395,14 @@ u16 leftADCInSens; // ADC left channel input sensitivity u16 rightADCInSens; // ADC right channel input sensitivity - int opencnt; // Open/Close count - int setcnt; // SetupForPlay count - int playcnt; // TriggerPlay count + int opencnt; // Open/Close count + int setcnt; // SetupForPlay count + int playcnt; // TriggerPlay count + int errorcnt; // Error Count + unsigned long totalerrorcnt; // Total Error Count + + int dsp_is_loaded; + int dsp_stop_is_processed; }; @@ -610,7 +610,7 @@ static void snd_korg1212_SendStop(korg1212_t *korg1212) { if (! korg1212->stop_pending_cnt) { - writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0xffffffff; /* program the timer */ korg1212->stop_pending_cnt = HZ; korg1212->timer.expires = jiffies + 1; @@ -622,9 +622,10 @@ { unsigned long flags; spin_lock_irqsave(&korg1212->lock, flags); + korg1212->dsp_stop_is_processed = 0; snd_korg1212_SendStop(korg1212); spin_unlock_irqrestore(&korg1212->lock, flags); - sleep_on_timeout(&korg1212->wait, (HZ * 3) / 2); + wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2); } /* timer callback for checking the ack of stop request */ @@ -633,9 +634,10 @@ korg1212_t *korg1212 = (korg1212_t *) data; spin_lock(&korg1212->lock); - if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) { + if (korg1212->sharedBufferPtr->cardCommand == 0) { /* ack'ed */ korg1212->stop_pending_cnt = 0; + korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait); #if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: Stop ack'ed [%s]\n", stateName[korg1212->cardState]); @@ -647,7 +649,8 @@ add_timer(&korg1212->timer); } else { snd_printd("korg1212_timer_func timeout\n"); - writel(0, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0; + korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait); #if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", stateName[korg1212->cardState]); @@ -850,15 +853,12 @@ static inline int snd_korg1212_use_is_exclusive(korg1212_t *korg1212) { - unsigned long flags; int ret = 1; - spin_lock_irqsave(&korg1212->lock, flags); if ((korg1212->playback_pid != korg1212->capture_pid) && (korg1212->playback_pid >= 0) && (korg1212->capture_pid >= 0)) { ret = 0; } - spin_unlock_irqrestore(&korg1212->lock, flags); return ret; } @@ -1179,18 +1179,23 @@ #if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); #endif - if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) + if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) { + korg1212->dsp_is_loaded = 1; wake_up(&korg1212->wait); + } break; // ------------------------------------------------------------------------ // an error occurred - stop the card // ------------------------------------------------------------------------ - case K1212_ISRCODE_DMAERROR: + case K1212_DB_DMAERROR: #if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); #endif - writel(0, &korg1212->sharedBufferPtr->cardCommand); + snd_printk(KERN_ERR "korg1212: DMA Error\n"); + korg1212->errorcnt++; + korg1212->totalerrorcnt++; + korg1212->sharedBufferPtr->cardCommand = 0; snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP); break; @@ -1198,11 +1203,11 @@ // the card has stopped by our request. Clear the command word and signal // the semaphore in case someone is waiting for this. // ------------------------------------------------------------------------ - case K1212_ISRCODE_CARDSTOPPED: + case K1212_DB_CARDSTOPPED: #if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); #endif - writel(0, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0; break; default: @@ -1267,7 +1272,9 @@ if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", rc, stateName[korg1212->cardState]); #endif - if (! sleep_on_timeout(&korg1212->wait, HZ * CARD_BOOT_TIMEOUT)) + korg1212->dsp_is_loaded = 0; + wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT); + if (! korg1212->dsp_is_loaded ) return -EBUSY; /* timeout */ snd_korg1212_OnDSPDownloadComplete(korg1212); @@ -1439,6 +1446,7 @@ korg1212->playback_pid = current->pid; korg1212->periodsize = K1212_PERIODS; korg1212->channels = K1212_CHANNELS; + korg1212->errorcnt = 0; spin_unlock_irqrestore(&korg1212->lock, flags); @@ -1457,7 +1465,7 @@ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", stateName[korg1212->cardState]); #endif - snd_pcm_set_sync(substream); // ??? + snd_pcm_set_sync(substream); snd_korg1212_OpenCard(korg1212); @@ -1614,7 +1622,7 @@ spin_unlock_irq(&korg1212->lock); return -EAGAIN; /* - writel(0, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0; del_timer(&korg1212->timer); korg1212->stop_pending_cnt = 0; */ @@ -2118,6 +2126,7 @@ snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn); snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount); snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount); + snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt); } static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212) @@ -2235,6 +2244,7 @@ korg1212->opencnt = 0; korg1212->playcnt = 0; korg1212->setcnt = 0; + korg1212->totalerrorcnt = 0; korg1212->playback_pid = -1; korg1212->capture_pid = -1; snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED); @@ -2273,7 +2283,7 @@ #endif if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, + snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, korg1212->iomem + iomem_size - 1); snd_korg1212_free(korg1212); return -EBUSY; @@ -2284,7 +2294,7 @@ "korg1212", (void *) korg1212); if (err) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); snd_korg1212_free(korg1212); return -EBUSY; } @@ -2332,7 +2342,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) { - snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer)); + snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer)); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2349,7 +2359,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->DataBufsSize, &korg1212->dma_play) < 0) { - snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); + snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2363,7 +2373,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->DataBufsSize, &korg1212->dma_rec) < 0) { - snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); + snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2395,7 +2405,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) { - snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize); + snd_printk(KERN_ERR "korg1212: can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2424,11 +2434,12 @@ if (snd_korg1212_downloadDSPCode(korg1212)) return -EBUSY; - printk(KERN_INFO "dspMemPhy = %08x U[%08x]\n" - "PlayDataPhy = %08x L[%08x]\n" - "RecDataPhy = %08x L[%08x]\n" - "VolumeTablePhy = %08x L[%08x]\n" - "RoutingTablePhy = %08x L[%08x]\n" + snd_printk(KERN_ERR + "korg1212: dspMemPhy = %08x U[%08x], " + "PlayDataPhy = %08x L[%08x]\n" + "korg1212: RecDataPhy = %08x L[%08x], " + "VolumeTablePhy = %08x L[%08x]\n" + "korg1212: RoutingTablePhy = %08x L[%08x], " "AdatTimeCodePhy = %08x L[%08x]\n", (int)korg1212->dma_dsp.addr, UpperWordSwap(korg1212->dma_dsp.addr), korg1212->PlayDataPhy, LowerWordSwap(korg1212->PlayDataPhy), diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c --- a/sound/pci/maestro3.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/maestro3.c 2005-03-03 21:43:47 -08:00 @@ -820,7 +820,7 @@ unsigned long iobase; int irq; - int allegro_flag : 1; + unsigned int allegro_flag : 1; ac97_t *ac97; @@ -957,6 +957,13 @@ .device = 0x80f1, .amp_gpio = 0x03, }, + /* LEGEND ZhaoYang 3100CF */ + { + .name = "LEGEND ZhaoYang 3100CF", + .vendor = 0x1509, + .device = 0x1740, + .amp_gpio = 0x03, + }, /* END */ { NULL } }; @@ -2385,7 +2392,7 @@ * APM support */ #ifdef CONFIG_PM -static int m3_suspend(snd_card_t *card, unsigned int state) +static int m3_suspend(snd_card_t *card, pm_message_t state) { m3_t *chip = card->pm_private_data; int i, index; @@ -2417,7 +2424,7 @@ return 0; } -static int m3_resume(snd_card_t *card, unsigned int state) +static int m3_resume(snd_card_t *card) { m3_t *chip = card->pm_private_data; int i, index; diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c --- a/sound/pci/nm256/nm256.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/nm256/nm256.c 2005-03-03 21:43:47 -08:00 @@ -1267,7 +1267,7 @@ * APM event handler, so the card is properly reinitialized after a power * event. */ -static int nm256_suspend(snd_card_t *card, unsigned int state) +static int nm256_suspend(snd_card_t *card, pm_message_t state) { nm256_t *chip = card->pm_private_data; @@ -1278,7 +1278,7 @@ return 0; } -static int nm256_resume(snd_card_t *card, unsigned int state) +static int nm256_resume(snd_card_t *card) { nm256_t *chip = card->pm_private_data; diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c --- a/sound/pci/rme9652/hdsp.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/rme9652/hdsp.c 2005-03-03 21:43:47 -08:00 @@ -47,8 +47,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ -static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface."); @@ -56,10 +54,6 @@ MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards."); -module_param_array(precise_ptr, bool, NULL, 0444); -MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably)."); -module_param_array(line_outs_monitor, bool, NULL, 0444); -MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default."); MODULE_AUTHOR("Paul Davis , Marcus Andersson, Thomas Charbonnel "); MODULE_DESCRIPTION("RME Hammerfall DSP"); MODULE_LICENSE("GPL"); @@ -445,6 +439,7 @@ snd_pcm_substream_t *playback_substream; hdsp_midi_t midi[2]; struct tasklet_struct midi_tasklet; + int use_midi_tasklet; int precise_ptr; u32 control_register; /* cached value */ u32 control2_register; /* cached value */ @@ -472,7 +467,6 @@ pid_t capture_pid; pid_t playback_pid; int running; - int passthru; /* non-zero if doing pass-thru */ int system_sample_rate; char *channel_map; int dev; @@ -659,13 +653,13 @@ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk ("loading firmware\n"); + snd_printk ("Hammerfall-DSP: loading firmware\n"); hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); hdsp_write (hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("timeout waiting for download preparation\n"); + snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); return -EIO; } @@ -674,7 +668,7 @@ for (i = 0; i < 24413; ++i) { hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { - snd_printk ("timeout during firmware loading\n"); + snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); return -EIO; } } @@ -687,7 +681,7 @@ } if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("timeout at end of firmware loading\n"); + snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); return -EIO; } @@ -697,11 +691,11 @@ hdsp->control2_register = 0; #endif hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - snd_printk ("finished firmware loading\n"); + snd_printk ("Hammerfall-DSP: finished firmware loading\n"); } if (hdsp->state & HDSP_InitializationComplete) { - snd_printk("firmware loaded from cache, restoring defaults\n"); + snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); spin_lock_irqsave(&hdsp->lock, flags); snd_hdsp_set_defaults(hdsp); spin_unlock_irqrestore(&hdsp->lock, flags); @@ -714,16 +708,6 @@ static int hdsp_get_iobox_version (hdsp_t *hdsp) { - int err; - - if (hdsp_check_for_iobox (hdsp)) { - return -EIO; - } - - if ((err = snd_hdsp_enable_io(hdsp)) < 0) { - return err; - } - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); @@ -759,7 +743,7 @@ { if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk("firmware not present.\n"); + snd_printk("Hammerfall-DSP: firmware not present.\n"); hdsp->state &= ~HDSP_FirmwareLoaded; return -EIO; } @@ -787,7 +771,7 @@ udelay (100); } - snd_printk ("wait for FIFO status <= %d failed after %d iterations\n", + snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n", count, timeout); return -1; } @@ -809,7 +793,7 @@ if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { - /* from martin björnsen: + /* from martin bjornsen: "You can only write dwords to the mixer memory which contain two @@ -922,7 +906,7 @@ default: break; } - snd_printk ("unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); + snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); return 0; } @@ -1008,7 +992,7 @@ if (!(hdsp->control_register & HDSP_ClockModeMaster)) { if (called_internally) { /* request from ctl or card initialization */ - snd_printk("device is not running as a clock master: cannot set sample rate.\n"); + snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); return -1; } else { /* hw_param request while in AutoSync mode */ @@ -1016,11 +1000,11 @@ int spdif_freq = hdsp_spdif_sample_rate(hdsp); if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { - snd_printk("Detected ADAT in double speed mode\n"); + snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n"); } else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { - snd_printk("Detected ADAT in quad speed mode\n"); + snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n"); } else if (rate != external_freq) { - snd_printk("No AutoSync source for requested rate\n"); + snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n"); return -1; } } @@ -1102,7 +1086,7 @@ } if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) { - snd_printk ("cannot change speed mode (capture PID = %d, playback PID = %d)\n", + snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n", hdsp->capture_pid, hdsp->playback_pid); return -EBUSY; @@ -1143,68 +1127,6 @@ return 0; } -static void hdsp_set_thru(hdsp_t *hdsp, int channel, int enable) -{ - - hdsp->passthru = 0; - - if (channel < 0) { - - int i; - - /* set thru for all channels */ - - if (enable) { - for (i = 0; i < hdsp->max_channels; i++) { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN); - } - } else { - for (i = 0; i < hdsp->max_channels; i++) { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN); - } - } - - } else { - int mapped_channel; - - snd_assert(channel < hdsp->max_channels, return); - - mapped_channel = hdsp->channel_map[channel]; - - snd_assert(mapped_channel > -1, return); - - if (enable) { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN); - } else { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN); - } - } -} - -static int hdsp_set_passthru(hdsp_t *hdsp, int onoff) -{ - if (onoff) { - hdsp_set_thru(hdsp, -1, 1); - hdsp_reset_hw_pointer(hdsp); - hdsp_silence_playback(hdsp); - - /* we don't want interrupts, so do a - custom version of hdsp_start_audio(). - */ - - hdsp->control_register |= (HDSP_Start|HDSP_AudioInterruptEnable|hdsp_encode_latency(7)); - - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->passthru = 1; - } else { - hdsp_set_thru(hdsp, -1, 0); - hdsp_stop_audio(hdsp); - hdsp->passthru = 0; - } - - return 0; -} - /*---------------------------------------------------------------------------- MIDI ----------------------------------------------------------------------------*/ @@ -1345,6 +1267,7 @@ } } else { hdsp->control_register &= ~ie; + tasklet_kill(&hdsp->midi_tasklet); } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); @@ -2741,16 +2664,32 @@ return 0; } -#define HDSP_PASSTHRU(xname, xindex) \ +#define HDSP_LINE_OUT(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ .name = xname, \ .index = xindex, \ - .info = snd_hdsp_info_passthru, \ - .put = snd_hdsp_put_passthru, \ - .get = snd_hdsp_get_passthru \ + .info = snd_hdsp_info_line_out, \ + .get = snd_hdsp_get_line_out, \ + .put = snd_hdsp_put_line_out \ +} + +static int hdsp_line_out(hdsp_t *hdsp) +{ + return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; +} + +static int hdsp_set_line_output(hdsp_t *hdsp, int out) +{ + if (out) { + hdsp->control_register |= HDSP_LineOut; + } else { + hdsp->control_register &= ~HDSP_LineOut; + } + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + return 0; } -static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -2759,61 +2698,106 @@ return 0; } -static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); - + spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp->passthru; + ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); spin_unlock_irq(&hdsp->lock); return 0; } -static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; - int err = 0; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); - change = (ucontrol->value.integer.value[0] != hdsp->passthru); - if (change) - err = hdsp_set_passthru(hdsp, val); + change = (int)val != hdsp_line_out(hdsp); + hdsp_set_line_output(hdsp, val); spin_unlock_irq(&hdsp->lock); - return err ? err : change; + return change; } -#define HDSP_LINE_OUT(xname, xindex) \ +#define HDSP_PRECISE_POINTER(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ .name = xname, \ .index = xindex, \ - .info = snd_hdsp_info_line_out, \ - .get = snd_hdsp_get_line_out, \ - .put = snd_hdsp_put_line_out \ + .info = snd_hdsp_info_precise_pointer, \ + .get = snd_hdsp_get_precise_pointer, \ + .put = snd_hdsp_put_precise_pointer \ } -static int hdsp_line_out(hdsp_t *hdsp) +static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise) { - return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; + if (precise) { + hdsp->precise_ptr = 1; + } else { + hdsp->precise_ptr = 0; + } + return 0; } -static int hdsp_set_line_output(hdsp_t *hdsp, int out) +static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { - if (out) { - hdsp->control_register |= HDSP_LineOut; + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); + + spin_lock_irq(&hdsp->lock); + ucontrol->value.integer.value[0] = hdsp->precise_ptr; + spin_unlock_irq(&hdsp->lock); + return 0; +} + +static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); + int change; + unsigned int val; + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; + val = ucontrol->value.integer.value[0] & 1; + spin_lock_irq(&hdsp->lock); + change = (int)val != hdsp->precise_ptr; + hdsp_set_precise_pointer(hdsp, val); + spin_unlock_irq(&hdsp->lock); + return change; +} + +#define HDSP_USE_MIDI_TASKLET(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdsp_info_use_midi_tasklet, \ + .get = snd_hdsp_get_use_midi_tasklet, \ + .put = snd_hdsp_put_use_midi_tasklet \ +} + +static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet) +{ + if (use_tasklet) { + hdsp->use_midi_tasklet = 1; } else { - hdsp->control_register &= ~HDSP_LineOut; + hdsp->use_midi_tasklet = 0; } - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } -static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -2822,17 +2806,17 @@ return 0; } -static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); + ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; spin_unlock_irq(&hdsp->lock); return 0; } -static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; @@ -2842,8 +2826,8 @@ return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_line_out(hdsp); - hdsp_set_line_output(hdsp, val); + change = (int)val != hdsp->use_midi_tasklet; + hdsp_set_use_midi_tasklet(hdsp, val); spin_unlock_irq(&hdsp->lock); return change; } @@ -3139,8 +3123,9 @@ HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0), HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0), HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0), -HDSP_PASSTHRU("Passthru", 0), HDSP_LINE_OUT("Line Out", 0), +HDSP_PRECISE_POINTER("Precise Pointer", 0), +HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), }; static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); @@ -3240,11 +3225,11 @@ snd_iprintf(buffer, "Status register: 0x%x\n", status); snd_iprintf(buffer, "Status2 register: 0x%x\n", status2); snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff); - snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0)); snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0)); snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1)); snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1)); + snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off"); snd_iprintf(buffer, "\n"); @@ -3252,7 +3237,7 @@ snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes); snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp)); - snd_iprintf(buffer, "Passthru: %s\n", hdsp->passthru ? "yes" : "no"); + snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off"); snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off"); snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2); @@ -3612,40 +3597,6 @@ } } - if ((hdsp->io_type != H9652) && line_outs_monitor[hdsp->dev]) { - - int lineouts_base; - - snd_printk ("sending all inputs and playback streams to line outs.\n"); - - /* route all inputs to the line outs for easy monitoring. send - odd numbered channels to right, even to left. - */ - if (hdsp->io_type == H9632) { - /* this is the phones/analog output */ - lineouts_base = 10; - } else { - lineouts_base = 26; - } - - for (i = 0; i < hdsp->max_channels; i++) { - if (i & 1) { - if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN) || - hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN)) { - return -EIO; - } - } else { - if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN) || - hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN)) { - - return -EIO; - } - } - } - } - - hdsp->passthru = 0; - /* H9632 specific defaults */ if (hdsp->io_type == H9632) { hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); @@ -3709,21 +3660,29 @@ } if (midi0 && midi0status) { - /* we disable interrupts for this input until processing is done */ - hdsp->control_register &= ~HDSP_Midi0InterruptEnable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->midi[0].pending = 1; - schedule = 1; + if (hdsp->use_midi_tasklet) { + /* we disable interrupts for this input until processing is done */ + hdsp->control_register &= ~HDSP_Midi0InterruptEnable; + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + hdsp->midi[0].pending = 1; + schedule = 1; + } else { + snd_hdsp_midi_input_read (&hdsp->midi[0]); + } } - if (midi1 && midi1status) { - /* we disable interrupts for this input until processing is done */ - hdsp->control_register &= ~HDSP_Midi1InterruptEnable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->midi[1].pending = 1; - schedule = 1; + if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) { + if (hdsp->use_midi_tasklet) { + /* we disable interrupts for this input until processing is done */ + hdsp->control_register &= ~HDSP_Midi1InterruptEnable; + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + hdsp->midi[1].pending = 1; + schedule = 1; + } else { + snd_hdsp_midi_input_read (&hdsp->midi[1]); + } } - if (schedule) - tasklet_hi_schedule(&hdsp->midi_tasklet); + if (hdsp->use_midi_tasklet && schedule) + tasklet_hi_schedule(&hdsp->midi_tasklet); return IRQ_HANDLED; } @@ -3838,10 +3797,10 @@ if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -3957,10 +3916,10 @@ if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4035,10 +3994,10 @@ if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4057,7 +4016,11 @@ SNDRV_PCM_INFO_NONINTERLEAVED | SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE), +#ifdef SNDRV_BIG_ENDIAN + .formats = SNDRV_PCM_FMTBIT_S32_BE, +#else .formats = SNDRV_PCM_FMTBIT_S32_LE, +#endif .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | @@ -4082,7 +4045,11 @@ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_NONINTERLEAVED | SNDRV_PCM_INFO_SYNC_START), +#ifdef SNDRV_BIG_ENDIAN + .formats = SNDRV_PCM_FMTBIT_S32_BE, +#else .formats = SNDRV_PCM_FMTBIT_S32_LE, +#endif .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | @@ -4290,10 +4257,10 @@ if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4306,11 +4273,6 @@ runtime->dma_area = hdsp->playback_buffer; runtime->dma_bytes = HDSP_DMA_AREA_BYTES; - if (hdsp->capture_substream == NULL) { - hdsp_stop_audio(hdsp); - hdsp_set_thru(hdsp, -1, 0); - } - hdsp->playback_pid = current->pid; hdsp->playback_substream = substream; @@ -4373,10 +4335,10 @@ if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4389,11 +4351,6 @@ runtime->dma_area = hdsp->capture_buffer; runtime->dma_bytes = HDSP_DMA_AREA_BYTES; - if (hdsp->playback_substream == NULL) { - hdsp_stop_audio(hdsp); - hdsp_set_thru(hdsp, -1, 0); - } - hdsp->capture_pid = current->pid; hdsp->capture_substream = substream; @@ -4553,12 +4510,12 @@ } for (i = 0; i < 26; ++i) { if (copy_u64_le(&peak_rms->playback_rms[i], - hdsp->iobase + HDSP_playbackRmsLevel + i * 8, - hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4)) + hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, + hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) return -EFAULT; if (copy_u64_le(&peak_rms->input_rms[i], - hdsp->iobase + HDSP_inputRmsLevel + i * 8, - hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4)) + hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, + hdsp->iobase + HDSP_inputRmsLevel + i * 8)) return -EFAULT; } return 0; @@ -4574,7 +4531,7 @@ hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg; if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); return -EINVAL; } @@ -4593,7 +4550,7 @@ int i; if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk("Firmware needs to be uploaded to the card.\n"); + snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); return -EINVAL; } spin_lock_irqsave(&hdsp->lock, flags); @@ -4618,7 +4575,6 @@ info.clock_source = (unsigned char)hdsp_clock_source(hdsp); info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); info.line_out = (unsigned char)hdsp_line_out(hdsp); - info.passthru = (unsigned char)hdsp->passthru; if (hdsp->io_type == H9632) { info.da_gain = (unsigned char)hdsp_da_gain(hdsp); info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); @@ -4661,7 +4617,6 @@ } break; } -#ifndef HDSP_FW_LOADER case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: { hdsp_firmware_t __user *firmware; u32 __user *firmware_data; @@ -4674,7 +4629,7 @@ if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) return -EBUSY; - snd_printk("initializing firmware upload\n"); + snd_printk("Hammerfall-DSP: initializing firmware upload\n"); firmware = (hdsp_firmware_t __user *)argp; if (get_user(firmware_data, &firmware->firmware_data)) { @@ -4696,18 +4651,20 @@ } if (!(hdsp->state & HDSP_InitializationComplete)) { - snd_hdsp_initialize_channels(hdsp); - + if ((err = snd_hdsp_enable_io(hdsp)) < 0) { + return err; + } + + snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk("error creating alsa devices\n"); + snd_printk("Hammerfall-DSP: error creating alsa devices\n"); return err; } } break; } -#endif case SNDRV_HDSP_IOCTL_GET_MIXER: { hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp; if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE)) @@ -4794,6 +4751,7 @@ int i; if (hdsp_fifo_wait (hdsp, 0, 100)) { + snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n"); return -EIO; } @@ -4859,24 +4817,25 @@ int err; if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { - snd_printk("Error creating pcm interface\n"); + snd_printk("Hammerfall-DSP: Error creating pcm interface\n"); return err; } if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { - snd_printk("Error creating first midi interface\n"); + snd_printk("Hammerfall-DSP: Error creating first midi interface\n"); return err; } - - if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { - snd_printk("Error creating second midi interface\n"); - return err; + if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { + if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { + snd_printk("Hammerfall-DSP: Error creating second midi interface\n"); + return err; + } } if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { - snd_printk("Error creating ctl interface\n"); + snd_printk("Hammerfall-DSP: Error creating ctl interface\n"); return err; } @@ -4889,7 +4848,7 @@ hdsp->playback_substream = NULL; if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { - snd_printk("Error setting default values\n"); + snd_printk("Hammerfall-DSP: Error setting default values\n"); return err; } @@ -4898,7 +4857,7 @@ hdsp->port, hdsp->irq); if ((err = snd_card_register(card)) < 0) { - snd_printk("error registering card\n"); + snd_printk("Hammerfall-DSP: error registering card\n"); return err; } hdsp->state |= HDSP_InitializationComplete; @@ -4923,9 +4882,7 @@ if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; } - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - + /* caution: max length of firmware filename is 30! */ switch (hdsp->io_type) { case Multiface: @@ -4941,16 +4898,16 @@ fwfile = "digiface_firmware_rev11.bin"; break; default: - snd_printk(KERN_ERR "hdsp: invalid io_type %d\n", hdsp->io_type); + snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type); return -EINVAL; } if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) { - snd_printk(KERN_ERR "hdsp: cannot load firmware %s\n", fwfile); + snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); return -ENOENT; } if (fw->size < sizeof(hdsp->firmware_cache)) { - snd_printk(KERN_ERR "hdsp: too short firmware size %d (expected %d)\n", + snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", (int)fw->size, (int)sizeof(hdsp->firmware_cache)); release_firmware(fw); return -EINVAL; @@ -4958,7 +4915,7 @@ #ifdef SNDRV_BIG_ENDIAN { int i; - u32 *src = (void *)fw->data; + u32 *src = (u32*)fw->data; for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++) hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) | ((*src & 0x0000ff00) << 8) | @@ -4969,17 +4926,25 @@ memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); #endif release_firmware(fw); - + hdsp->state |= HDSP_FirmwareCached; if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) return err; if (!(hdsp->state & HDSP_InitializationComplete)) { + if ((err = snd_hdsp_enable_io(hdsp)) < 0) { + return err; + } + + if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { + snd_printk("Hammerfall-DSP: error creating hwdep device\n"); + return err; + } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk("error creating alsa devices\n"); + snd_printk("Hammerfall-DSP: error creating alsa devices\n"); return err; } } @@ -4988,8 +4953,7 @@ #endif static int __devinit snd_hdsp_create(snd_card_t *card, - hdsp_t *hdsp, - int precise_ptr) + hdsp_t *hdsp) { struct pci_dev *pci = hdsp->pci; int err; @@ -5004,6 +4968,8 @@ hdsp->midi[1].input = NULL; hdsp->midi[0].output = NULL; hdsp->midi[1].output = NULL; + hdsp->midi[0].pending = 0; + hdsp->midi[1].pending = 0; spin_lock_init(&hdsp->midi[0].lock); spin_lock_init(&hdsp->midi[1].lock); hdsp->iobase = NULL; @@ -5019,6 +4985,7 @@ tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); + hdsp->firmware_rev &= 0xff; /* From Martin Bjoernsen : "It is important that the card's latency timer register in @@ -5032,27 +4999,17 @@ strcpy(card->driver, "H-DSP"); strcpy(card->mixername, "Xilinx FPGA"); - switch (hdsp->firmware_rev & 0xff) { - case 0xa: - case 0xb: - case 0x32: + if (hdsp->firmware_rev < 0xa) { + return -ENODEV; + } else if (hdsp->firmware_rev < 0x64) { hdsp->card_name = "RME Hammerfall DSP"; - break; - - case 0x64: - case 0x65: - case 0x68: + } else if (hdsp->firmware_rev < 0x96) { hdsp->card_name = "RME HDSP 9652"; is_9652 = 1; - break; - case 0x96: - case 0x97: + } else { hdsp->card_name = "RME HDSP 9632"; hdsp->max_channels = 16; - is_9632 = 1; - break; - default: - return -ENODEV; + is_9632 = 1; } if ((err = pci_enable_device(pci)) < 0) { @@ -5065,56 +5022,65 @@ return err; hdsp->port = pci_resource_start(pci, 0); if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { - snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); + snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; } if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) { - snd_printk("unable to use IRQ %d\n", pci->irq); + snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); return -EBUSY; } hdsp->irq = pci->irq; - hdsp->precise_ptr = precise_ptr; + hdsp->precise_ptr = 1; + hdsp->use_midi_tasklet = 1; if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) { return err; } - if (!is_9652 && !is_9632 && hdsp_check_for_iobox (hdsp)) { - /* no iobox connected, we defer initialization */ - snd_printk("card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { - return err; + if (!is_9652 && !is_9632) { + /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ + if ((1000 / HZ) < 2000) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((2000 * HZ + 999) / 1000); + } else { + mdelay(2000); + } + + if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { +#ifdef HDSP_FW_LOADER + if ((err = hdsp_request_fw_loader(hdsp)) < 0) { + /* we don't fail as this can happen + if userspace is not ready for + firmware upload + */ + snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); + } else { + /* init is complete, we return */ + return 0; + } +#endif + /* no iobox connected, we defer initialization */ + snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n"); + if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { + return err; + } + return 0; + } else { + snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n"); + if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { + hdsp->io_type = Multiface; + } else { + hdsp->io_type = Digiface; + } } - return 0; } if ((err = snd_hdsp_enable_io(hdsp)) != 0) { return err; } - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { -#ifdef HDSP_FW_LOADER - if ((err = hdsp_request_fw_loader(hdsp)) < 0) - return err; -#else - snd_printk("card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { - return err; - } - return 0; -#endif - } - - snd_printk("Firmware already loaded, initializing card.\n"); - - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { - hdsp->io_type = Multiface; - } else { - hdsp->io_type = Digiface; - } - if (is_9652) { hdsp->io_type = H9652; } @@ -5143,6 +5109,7 @@ { if (hdsp->port) { /* stop the audio, and cancel all interrupts */ + tasklet_kill(&hdsp->midi_tasklet); hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable); hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register); } @@ -5194,7 +5161,7 @@ hdsp->pci = pci; snd_card_set_dev(card, &pci->dev); - if ((err = snd_hdsp_create(card, hdsp, precise_ptr[dev])) < 0) { + if ((err = snd_hdsp_create(card, hdsp)) < 0) { snd_card_free(card); return err; } diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c --- a/sound/pci/trident/trident_main.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/trident/trident_main.c 2005-03-03 21:43:47 -08:00 @@ -48,8 +48,8 @@ static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream); static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs); #ifdef CONFIG_PM -static int snd_trident_suspend(snd_card_t *card, unsigned int state); -static int snd_trident_resume(snd_card_t *card, unsigned int state); +static int snd_trident_suspend(snd_card_t *card, pm_message_t state); +static int snd_trident_resume(snd_card_t *card); #endif static int snd_trident_sis_reset(trident_t *trident); @@ -3921,7 +3921,7 @@ } #ifdef CONFIG_PM -static int snd_trident_suspend(snd_card_t *card, unsigned int state) +static int snd_trident_suspend(snd_card_t *card, pm_message_t state) { trident_t *trident = card->pm_private_data; @@ -3947,7 +3947,7 @@ return 0; } -static int snd_trident_resume(snd_card_t *card, unsigned int state) +static int snd_trident_resume(snd_card_t *card) { trident_t *trident = card->pm_private_data; diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c --- a/sound/pci/via82xx.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/via82xx.c 2005-03-03 21:43:47 -08:00 @@ -1895,7 +1895,7 @@ /* * power management */ -static int snd_via82xx_suspend(snd_card_t *card, unsigned int state) +static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state) { via82xx_t *chip = card->pm_private_data; int i; @@ -1920,7 +1920,7 @@ return 0; } -static int snd_via82xx_resume(snd_card_t *card, unsigned int state) +static int snd_via82xx_resume(snd_card_t *card) { via82xx_t *chip = card->pm_private_data; int idx, i; diff -Nru a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c --- a/sound/pci/via82xx_modem.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/via82xx_modem.c 2005-03-03 21:43:47 -08:00 @@ -55,7 +55,7 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; @@ -1034,7 +1034,7 @@ /* * power management */ -static int snd_via82xx_suspend(snd_card_t *card, unsigned int state) +static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state) { via82xx_t *chip = card->pm_private_data; int i; @@ -1051,7 +1051,7 @@ return 0; } -static int snd_via82xx_resume(snd_card_t *card, unsigned int state) +static int snd_via82xx_resume(snd_card_t *card) { via82xx_t *chip = card->pm_private_data; int i; diff -Nru a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c --- a/sound/pci/vx222/vx222_ops.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pci/vx222/vx222_ops.c 2005-03-03 21:43:46 -08:00 @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff -Nru a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c --- a/sound/pci/ymfpci/ymfpci_main.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pci/ymfpci/ymfpci_main.c 2005-03-03 21:43:47 -08:00 @@ -2142,7 +2142,7 @@ }; #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) -static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state) +static int snd_ymfpci_suspend(snd_card_t *card, pm_message_t state) { ymfpci_t *chip = card->pm_private_data; unsigned int i; @@ -2161,7 +2161,7 @@ return 0; } -static int snd_ymfpci_resume(snd_card_t *card, unsigned int state) +static int snd_ymfpci_resume(snd_card_t *card) { ymfpci_t *chip = card->pm_private_data; unsigned int i; diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c 2005-03-03 21:43:47 -08:00 @@ -342,7 +342,7 @@ link->state |= DEV_SUSPEND; if (chip) { snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); - snd_pdacf_suspend(chip->card, 0); + snd_pdacf_suspend(chip->card, PMSG_SUSPEND); } /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: @@ -361,7 +361,7 @@ pcmcia_request_configuration(link->handle, &link->conf); if (chip) { snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); - snd_pdacf_resume(chip->card, 0); + snd_pdacf_resume(chip->card); } } snd_printdd(KERN_DEBUG "resume done!\n"); diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h 2005-03-03 21:43:46 -08:00 +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h 2005-03-03 21:43:46 -08:00 @@ -134,8 +134,8 @@ int snd_pdacf_ak4117_create(pdacf_t *pdacf); void snd_pdacf_powerdown(pdacf_t *chip); #ifdef CONFIG_PM -int snd_pdacf_suspend(snd_card_t *card, unsigned int state); -int snd_pdacf_resume(snd_card_t *card, unsigned int state); +int snd_pdacf_suspend(snd_card_t *card, pm_message_t state); +int snd_pdacf_resume(snd_card_t *card); #endif int snd_pdacf_pcm_new(pdacf_t *chip); irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs); diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c 2005-03-03 21:43:47 -08:00 @@ -255,7 +255,7 @@ #ifdef CONFIG_PM -int snd_pdacf_suspend(snd_card_t *card, unsigned int state) +int snd_pdacf_suspend(snd_card_t *card, pm_message_t state) { pdacf_t *chip = card->pm_private_data; u16 val; @@ -275,7 +275,7 @@ return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0; } -int snd_pdacf_resume(snd_card_t *card, unsigned int state) +int snd_pdacf_resume(snd_card_t *card) { pdacf_t *chip = card->pm_private_data; int timeout = 40; diff -Nru a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c --- a/sound/pcmcia/vx/vx_entry.c 2005-03-03 21:43:46 -08:00 +++ b/sound/pcmcia/vx/vx_entry.c 2005-03-03 21:43:46 -08:00 @@ -346,7 +346,7 @@ link->state |= DEV_SUSPEND; if (chip && chip->card->pm_suspend) { snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); - chip->card->pm_suspend(chip->card, 0); + chip->card->pm_suspend(chip->card, PMSG_SUSPEND); } /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: @@ -366,7 +366,7 @@ pcmcia_request_configuration(link->handle, &link->conf); if (chip && chip->card->pm_resume) { snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); - chip->card->pm_resume(chip->card, 0); + chip->card->pm_resume(chip->card); } } snd_printdd(KERN_DEBUG "resume done!\n"); diff -Nru a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c --- a/sound/pcmcia/vx/vxp_ops.c 2005-03-03 21:43:47 -08:00 +++ b/sound/pcmcia/vx/vxp_ops.c 2005-03-03 21:43:47 -08:00 @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff -Nru a/sound/ppc/pmac.c b/sound/ppc/pmac.c --- a/sound/ppc/pmac.c 2005-03-03 21:43:47 -08:00 +++ b/sound/ppc/pmac.c 2005-03-03 21:43:47 -08:00 @@ -40,8 +40,8 @@ #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) static int snd_pmac_register_sleep_notifier(pmac_t *chip); static int snd_pmac_unregister_sleep_notifier(pmac_t *chip); -static int snd_pmac_suspend(snd_card_t *card, unsigned int state); -static int snd_pmac_resume(snd_card_t *card, unsigned int state); +static int snd_pmac_suspend(snd_card_t *card, pm_message_t state); +static int snd_pmac_resume(snd_card_t *card); #endif @@ -1233,7 +1233,7 @@ * Save state when going to sleep, restore it afterwards. */ -static int snd_pmac_suspend(snd_card_t *card, unsigned int state) +static int snd_pmac_suspend(snd_card_t *card, pm_message_t state) { pmac_t *chip = card->pm_private_data; unsigned long flags; @@ -1254,7 +1254,7 @@ return 0; } -static int snd_pmac_resume(snd_card_t *card, unsigned int state) +static int snd_pmac_resume(snd_card_t *card) { pmac_t *chip = card->pm_private_data; @@ -1294,10 +1294,10 @@ switch (when) { case PBOOK_SLEEP_NOW: - snd_pmac_suspend(chip->card, 0); + snd_pmac_suspend(chip->card, PMSG_SUSPEND); break; case PBOOK_WAKE: - snd_pmac_resume(chip->card, 0); + snd_pmac_resume(chip->card); break; } return PBOOK_SLEEP_OK; diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c --- a/sound/usb/usbaudio.c 2005-03-03 21:43:47 -08:00 +++ b/sound/usb/usbaudio.c 2005-03-03 21:43:47 -08:00 @@ -2968,6 +2968,9 @@ case QUIRK_MIDI_FIXED_ENDPOINT: case QUIRK_MIDI_YAMAHA: case QUIRK_MIDI_MIDIMAN: + case QUIRK_MIDI_NOVATION: + case QUIRK_MIDI_MOTU: + case QUIRK_MIDI_EMAGIC: return snd_usb_create_midi_interface(chip, iface, quirk); case QUIRK_COMPOSITE: return create_composite_quirk(chip, iface, quirk); @@ -2980,6 +2983,8 @@ return create_ua700_ua25_quirk(chip, iface); case QUIRK_AUDIO_EDIROL_UA1000: return create_ua1000_quirk(chip, iface); + case QUIRK_IGNORE_INTERFACE: + return 0; default: snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); return -ENXIO; diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h --- a/sound/usb/usbaudio.h 2005-03-03 21:43:47 -08:00 +++ b/sound/usb/usbaudio.h 2005-03-03 21:43:47 -08:00 @@ -157,6 +157,10 @@ #define QUIRK_MIDI_STANDARD_INTERFACE 6 #define QUIRK_AUDIO_EDIROL_UA700_UA25 7 #define QUIRK_AUDIO_EDIROL_UA1000 8 +#define QUIRK_IGNORE_INTERFACE 9 +#define QUIRK_MIDI_NOVATION 10 +#define QUIRK_MIDI_MOTU 11 +#define QUIRK_MIDI_EMAGIC 12 typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; @@ -171,7 +175,10 @@ /* data for QUIRK_MIDI_FIXED_ENDPOINT */ struct snd_usb_midi_endpoint_info { - int8_t out_ep, in_ep; /* ep number, 0 autodetect */ + int8_t out_ep; /* ep number, 0 autodetect */ + uint8_t out_interval; /* interval for interrupt endpoints */ + int8_t in_ep; + uint8_t in_interval; uint16_t out_cables; /* bitmask */ uint16_t in_cables; /* bitmask */ }; @@ -189,6 +196,13 @@ /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ /* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ + +/* for QUIRK_IGNORE_INTERFACE, data is NULL */ + +/* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */ + +/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info + * structure (out_cables and in_cables only) */ /* */ diff -Nru a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c --- a/sound/usb/usbmidi.c 2005-03-03 21:43:47 -08:00 +++ b/sound/usb/usbmidi.c 2005-03-03 21:43:47 -08:00 @@ -1,7 +1,7 @@ /* * usbmidi.c - ALSA USB MIDI driver * - * Copyright (c) 2002-2004 Clemens Ladisch + * Copyright (c) 2002-2005 Clemens Ladisch * All rights reserved. * * Based on the OSS usb-midi driver by NAGANO Daisuke, @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,13 @@ #include #include "usbaudio.h" + +/* + * define this to log all USB packets + */ +/* #define DUMP_PACKETS */ + + MODULE_AUTHOR("Clemens Ladisch "); MODULE_DESCRIPTION("USB Audio/MIDI helper module"); MODULE_LICENSE("Dual BSD/GPL"); @@ -77,22 +85,33 @@ typedef struct usbmidi_out_port usbmidi_out_port_t; typedef struct usbmidi_in_port usbmidi_in_port_t; +struct usb_protocol_ops { + void (*input)(snd_usb_midi_in_endpoint_t*, uint8_t*, int); + void (*output)(snd_usb_midi_out_endpoint_t*); + void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t); + void (*init_out_endpoint)(snd_usb_midi_out_endpoint_t*); + void (*finish_out_endpoint)(snd_usb_midi_out_endpoint_t*); +}; + struct snd_usb_midi { snd_usb_audio_t *chip; struct usb_interface *iface; const snd_usb_audio_quirk_t *quirk; snd_rawmidi_t* rmidi; + struct usb_protocol_ops* usb_protocol_ops; struct list_head list; struct snd_usb_midi_endpoint { snd_usb_midi_out_endpoint_t *out; snd_usb_midi_in_endpoint_t *in; } endpoints[MIDI_MAX_ENDPOINTS]; + unsigned long input_triggered; }; struct snd_usb_midi_out_endpoint { snd_usb_midi_t* umidi; struct urb* urb; + int urb_active; int max_transfer; /* size of urb buffer */ struct tasklet_struct tasklet; @@ -113,6 +132,7 @@ #define STATE_SYSEX_2 6 uint8_t data[2]; } ports[0x10]; + int current_port; }; struct snd_usb_midi_in_endpoint { @@ -121,6 +141,8 @@ struct usbmidi_in_port { snd_rawmidi_substream_t* substream; } ports[0x10]; + int seen_f5; + int current_port; }; static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep); @@ -156,25 +178,34 @@ } /* - * Receives a USB MIDI packet. + * Receives a chunk of MIDI data. */ -static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep, - uint8_t packet[4]) +static void snd_usbmidi_input_data(snd_usb_midi_in_endpoint_t* ep, int portidx, + uint8_t* data, int length) { - int cable = packet[0] >> 4; - usbmidi_in_port_t* port = &ep->ports[cable]; + usbmidi_in_port_t* port = &ep->ports[portidx]; if (!port->substream) { - snd_printd("unexpected port %d!\n", cable); + snd_printd("unexpected port %d!\n", portidx); return; } - if (!port->substream->runtime || - !port->substream->runtime->trigger) + if (!test_bit(port->substream->number, &ep->umidi->input_triggered)) return; - snd_rawmidi_receive(port->substream, &packet[1], - snd_usbmidi_cin_length[packet[0] & 0x0f]); + snd_rawmidi_receive(port->substream, data, length); } +#ifdef DUMP_PACKETS +static void dump_urb(const char *type, const u8 *data, int length) +{ + snd_printk(KERN_DEBUG "%s packet: [", type); + for (; length > 0; ++data, --length) + printk(" %02x", *data); + printk(" ]\n"); +} +#else +#define dump_urb(type, data, length) /* nothing */ +#endif + /* * Processes the data read from the device. */ @@ -183,12 +214,9 @@ snd_usb_midi_in_endpoint_t* ep = urb->context; if (urb->status == 0) { - uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer; - int i; - - for (i = 0; i + 4 <= urb->actual_length; i += 4) - if (buffer[i] != 0) - snd_usbmidi_input_packet(ep, &buffer[i]); + dump_urb("received", urb->transfer_buffer, urb->actual_length); + ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer, + urb->actual_length); } else { if (snd_usbmidi_urb_error(urb->status) < 0) return; @@ -200,71 +228,107 @@ } } +static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs) +{ + snd_usb_midi_out_endpoint_t* ep = urb->context; + + spin_lock(&ep->buffer_lock); + ep->urb_active = 0; + spin_unlock(&ep->buffer_lock); + if (urb->status < 0) { + if (snd_usbmidi_urb_error(urb->status) < 0) + return; + } + snd_usbmidi_do_output(ep); +} + /* - * Converts the data read from a Midiman device to standard USB MIDI packets. + * This is called when some data should be transferred to the device + * (from one or more substreams). */ -static void snd_usbmidi_in_midiman_complete(struct urb* urb, struct pt_regs *regs) +static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep) { - if (urb->status == 0) { - uint8_t* buffer = (uint8_t*)urb->transfer_buffer; - int i; + struct urb* urb = ep->urb; + unsigned long flags; - for (i = 0; i + 4 <= urb->actual_length; i += 4) { - if (buffer[i + 3] != 0) { - /* - * snd_usbmidi_input_packet() doesn't check the - * contents of the message, so we simply use - * some random CIN with the desired length. - */ - static const uint8_t cin[4] = { - 0x0, 0xf, 0x2, 0x3 - }; - uint8_t ctl = buffer[i + 3]; - buffer[i + 3] = buffer[i + 2]; - buffer[i + 2] = buffer[i + 1]; - buffer[i + 1] = buffer[i + 0]; - buffer[i + 0] = (ctl & 0xf0) | cin[ctl & 3]; - } else { - buffer[i + 0] = 0; - } - } + spin_lock_irqsave(&ep->buffer_lock, flags); + if (ep->urb_active || ep->umidi->chip->shutdown) { + spin_unlock_irqrestore(&ep->buffer_lock, flags); + return; } - snd_usbmidi_in_urb_complete(urb, regs); + + urb->transfer_buffer_length = 0; + ep->umidi->usb_protocol_ops->output(ep); + + if (urb->transfer_buffer_length > 0) { + dump_urb("sending", urb->transfer_buffer, + urb->transfer_buffer_length); + urb->dev = ep->umidi->chip->dev; + ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0; + } + spin_unlock_irqrestore(&ep->buffer_lock, flags); } -static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs) +static void snd_usbmidi_out_tasklet(unsigned long data) { - snd_usb_midi_out_endpoint_t* ep = urb->context; + snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data; - if (urb->status < 0) { - if (snd_usbmidi_urb_error(urb->status) < 0) - return; - } snd_usbmidi_do_output(ep); } +/* helper function to send static data that may not DMA-able */ +static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep, + const void *data, int len) +{ + int err; + void *buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + memcpy(buf, data, len); + dump_urb("sending", buf, len); + err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len, + NULL, HZ / 4); + kfree(buf); + return err; +} + /* - * Converts standard USB MIDI packets to what Midman devices expect. + * Standard USB MIDI protocol: see the spec. + * Midiman protocol: like the standard protocol, but the control byte is the + * fourth byte in each packet, and uses length instead of CIN. */ -static void snd_usbmidi_convert_to_midiman(struct urb* urb) + +static void snd_usbmidi_standard_input(snd_usb_midi_in_endpoint_t* ep, + uint8_t* buffer, int buffer_length) { - uint8_t* buffer = (uint8_t*)urb->transfer_buffer; int i; - for (i = 0; i + 4 <= urb->transfer_buffer_length; i += 4) { - uint8_t cin = buffer[i]; - buffer[i + 0] = buffer[i + 1]; - buffer[i + 1] = buffer[i + 2]; - buffer[i + 2] = buffer[i + 3]; - buffer[i + 3] = (cin & 0xf0) | snd_usbmidi_cin_length[cin & 0x0f]; - } + for (i = 0; i + 3 < buffer_length; i += 4) + if (buffer[i] != 0) { + int cable = buffer[i] >> 4; + int length = snd_usbmidi_cin_length[buffer[i] & 0x0f]; + snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length); + } +} + +static void snd_usbmidi_midiman_input(snd_usb_midi_in_endpoint_t* ep, + uint8_t* buffer, int buffer_length) +{ + int i; + + for (i = 0; i + 3 < buffer_length; i += 4) + if (buffer[i + 3] != 0) { + int port = buffer[i + 3] >> 4; + int length = buffer[i + 3] & 3; + snd_usbmidi_input_data(ep, port, &buffer[i], length); + } } /* * Adds one USB MIDI packet to the output buffer. */ -static inline void output_packet(struct urb* urb, - uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3) +static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, + uint8_t p1, uint8_t p2, uint8_t p3) { uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length; @@ -276,12 +340,29 @@ } /* + * Adds one Midiman packet to the output buffer. + */ +static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0, + uint8_t p1, uint8_t p2, uint8_t p3) +{ + + uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length; + buf[0] = p1; + buf[1] = p2; + buf[2] = p3; + buf[3] = (p0 & 0xf0) | snd_usbmidi_cin_length[p0 & 0x0f]; + urb->transfer_buffer_length += 4; +} + +/* * Converts MIDI commands to USB MIDI packets. */ static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port, uint8_t b, struct urb* urb) { uint8_t p0 = port->cable; + void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) = + port->ep->umidi->usb_protocol_ops->output_packet; if (b >= 0xf8) { output_packet(urb, p0 | 0x0f, b, 0, 0); @@ -370,63 +451,237 @@ } } -/* - * Moves data from one substream buffer to the URB transfer buffer. - */ -static void snd_usbmidi_transmit(snd_usb_midi_out_endpoint_t* ep, int port_idx) +static void snd_usbmidi_standard_output(snd_usb_midi_out_endpoint_t* ep) { struct urb* urb = ep->urb; - usbmidi_out_port_t* port = &ep->ports[port_idx]; + int p; - while (urb->transfer_buffer_length < ep->max_transfer) { - uint8_t b; - if (snd_rawmidi_transmit_peek(port->substream, &b, 1) != 1) { - port->active = 0; - break; + /* FIXME: lower-numbered ports can starve higher-numbered ports */ + for (p = 0; p < 0x10; ++p) { + usbmidi_out_port_t* port = &ep->ports[p]; + if (!port->active) + continue; + while (urb->transfer_buffer_length + 3 < ep->max_transfer) { + uint8_t b; + if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) { + port->active = 0; + break; + } + snd_usbmidi_transmit_byte(port, b, urb); } - snd_usbmidi_transmit_byte(port, b, urb); - snd_rawmidi_transmit_ack(port->substream, 1); } } +static struct usb_protocol_ops snd_usbmidi_standard_ops = { + .input = snd_usbmidi_standard_input, + .output = snd_usbmidi_standard_output, + .output_packet = snd_usbmidi_output_standard_packet, +}; + +static struct usb_protocol_ops snd_usbmidi_midiman_ops = { + .input = snd_usbmidi_midiman_input, + .output = snd_usbmidi_standard_output, + .output_packet = snd_usbmidi_output_midiman_packet, +}; + /* - * This is called when some data should be transferred to the device - * (from one or more substreams). + * Novation USB MIDI protocol: number of data bytes is in the first byte + * (when receiving) (+1!) or in the second byte (when sending); data begins + * at the third byte. */ -static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep) + +static void snd_usbmidi_novation_input(snd_usb_midi_in_endpoint_t* ep, + uint8_t* buffer, int buffer_length) { - int p; - struct urb* urb = ep->urb; - unsigned long flags; + if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1) + return; + snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1); +} - spin_lock_irqsave(&ep->buffer_lock, flags); - if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) { - spin_unlock_irqrestore(&ep->buffer_lock, flags); +static void snd_usbmidi_novation_output(snd_usb_midi_out_endpoint_t* ep) +{ + uint8_t* transfer_buffer; + int count; + + if (!ep->ports[0].active) + return; + transfer_buffer = ep->urb->transfer_buffer; + count = snd_rawmidi_transmit(ep->ports[0].substream, + &transfer_buffer[2], + ep->max_transfer - 2); + if (count < 1) { + ep->ports[0].active = 0; return; } + transfer_buffer[0] = 0; + transfer_buffer[1] = count; + ep->urb->transfer_buffer_length = 2 + count; +} - urb->transfer_buffer_length = 0; - for (p= 0; p < 0x10; ++p) - if (ep->ports[p].active) - snd_usbmidi_transmit(ep, p); +static struct usb_protocol_ops snd_usbmidi_novation_ops = { + .input = snd_usbmidi_novation_input, + .output = snd_usbmidi_novation_output, +}; - if (urb->transfer_buffer_length > 0) { - if (ep->umidi->quirk && ep->umidi->quirk->type == QUIRK_MIDI_MIDIMAN) - snd_usbmidi_convert_to_midiman(urb); +/* + * Mark of the Unicorn USB MIDI protocol: raw MIDI. + */ - urb->dev = ep->umidi->chip->dev; - snd_usbmidi_submit_urb(urb, GFP_ATOMIC); +static void snd_usbmidi_motu_input(snd_usb_midi_in_endpoint_t* ep, + uint8_t* buffer, int buffer_length) +{ + snd_usbmidi_input_data(ep, 0, buffer, buffer_length); +} + +static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep) +{ + int count; + + if (!ep->ports[0].active) + return; + count = snd_rawmidi_transmit(ep->ports[0].substream, + ep->urb->transfer_buffer, + ep->max_transfer); + if (count < 1) { + ep->ports[0].active = 0; + return; } - spin_unlock_irqrestore(&ep->buffer_lock, flags); + ep->urb->transfer_buffer_length = count; } -static void snd_usbmidi_out_tasklet(unsigned long data) +static struct usb_protocol_ops snd_usbmidi_motu_ops = { + .input = snd_usbmidi_motu_input, + .output = snd_usbmidi_motu_output, +}; + +/* + * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching. + */ + +static void snd_usbmidi_emagic_init_out(snd_usb_midi_out_endpoint_t* ep) { - snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data; + static const u8 init_data[] = { + /* initialization magic: "get version" */ + 0xf0, + 0x00, 0x20, 0x31, /* Emagic */ + 0x64, /* Unitor8 */ + 0x0b, /* version number request */ + 0x00, /* command version */ + 0x00, /* EEPROM, box 0 */ + 0xf7 + }; + send_bulk_static_data(ep, init_data, sizeof(init_data)); + /* while we're at it, pour on more magic */ + send_bulk_static_data(ep, init_data, sizeof(init_data)); +} + +static void snd_usbmidi_emagic_finish_out(snd_usb_midi_out_endpoint_t* ep) +{ + static const u8 finish_data[] = { + /* switch to patch mode with last preset */ + 0xf0, + 0x00, 0x20, 0x31, /* Emagic */ + 0x64, /* Unitor8 */ + 0x10, /* patch switch command */ + 0x00, /* command version */ + 0x7f, /* to all boxes */ + 0x40, /* last preset in EEPROM */ + 0xf7 + }; + send_bulk_static_data(ep, finish_data, sizeof(finish_data)); +} + +static void snd_usbmidi_emagic_input(snd_usb_midi_in_endpoint_t* ep, + uint8_t* buffer, int buffer_length) +{ + /* ignore padding bytes at end of buffer */ + while (buffer_length > 0 && buffer[buffer_length - 1] == 0xff) + --buffer_length; + + /* handle F5 at end of last buffer */ + if (ep->seen_f5) + goto switch_port; - snd_usbmidi_do_output(ep); + while (buffer_length > 0) { + int i; + + /* determine size of data until next F5 */ + for (i = 0; i < buffer_length; ++i) + if (buffer[i] == 0xf5) + break; + snd_usbmidi_input_data(ep, ep->current_port, buffer, i); + buffer += i; + buffer_length -= i; + + if (buffer_length <= 0) + break; + /* assert(buffer[0] == 0xf5); */ + ep->seen_f5 = 1; + ++buffer; + --buffer_length; + + switch_port: + if (buffer_length <= 0) + break; + if (buffer[0] < 0x80) { + ep->current_port = (buffer[0] - 1) & 15; + ++buffer; + --buffer_length; + } + ep->seen_f5 = 0; + } +} + +static void snd_usbmidi_emagic_output(snd_usb_midi_out_endpoint_t* ep) +{ + int port0 = ep->current_port; + uint8_t* buf = ep->urb->transfer_buffer; + int buf_free = ep->max_transfer; + int length, i; + + for (i = 0; i < 0x10; ++i) { + /* round-robin, starting at the last current port */ + int portnum = (port0 + i) & 15; + usbmidi_out_port_t* port = &ep->ports[portnum]; + + if (!port->active) + continue; + if (snd_rawmidi_transmit_peek(port->substream, buf, 1) != 1) { + port->active = 0; + continue; + } + + if (portnum != ep->current_port) { + if (buf_free < 2) + break; + ep->current_port = portnum; + buf[0] = 0xf5; + buf[1] = (portnum + 1) & 15; + buf += 2; + buf_free -= 2; + } + + if (buf_free < 1) + break; + length = snd_rawmidi_transmit(port->substream, buf, buf_free); + if (length > 0) { + buf += length; + buf_free -= length; + if (buf_free < 1) + break; + } + } + ep->urb->transfer_buffer_length = ep->max_transfer - buf_free; } +static struct usb_protocol_ops snd_usbmidi_emagic_ops = { + .input = snd_usbmidi_emagic_input, + .output = snd_usbmidi_emagic_output, + .init_out_endpoint = snd_usbmidi_emagic_init_out, + .finish_out_endpoint = snd_usbmidi_emagic_finish_out, +}; + + static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream) { snd_usb_midi_t* umidi = substream->rmidi->private_data; @@ -483,6 +738,12 @@ static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t* substream, int up) { + snd_usb_midi_t* umidi = substream->rmidi->private_data; + + if (up) + set_bit(substream->number, &umidi->input_triggered); + else + clear_bit(substream->number, &umidi->input_triggered); } static snd_rawmidi_ops_t snd_usbmidi_output_ops = { @@ -511,57 +772,6 @@ } /* - * For Roland devices, use the alternate setting which uses interrupt - * transfers for input. - */ -static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi) -{ - struct usb_interface* intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor* intfd; - - if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) != 0x0582) - return NULL; - intf = umidi->iface; - if (!intf || intf->num_altsetting != 2) - return NULL; - - hostif = &intf->altsetting[0]; - intfd = get_iface_desc(hostif); - if (intfd->bNumEndpoints != 2 || - (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK || - (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) - return NULL; - - hostif = &intf->altsetting[1]; - intfd = get_iface_desc(hostif); - if (intfd->bNumEndpoints != 2 || - (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK || - (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) - return NULL; - - snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n", - intfd->bAlternateSetting); - usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber, - intfd->bAlternateSetting); - return get_endpoint(hostif, 1); -} - -static struct usb_endpoint_descriptor* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi) -{ - struct usb_interface* intf = umidi->iface; - struct usb_host_interface *hostif; - struct usb_interface_descriptor *intfd; - if (!intf) - return NULL; - hostif = &intf->altsetting[0]; - intfd = get_iface_desc(hostif); - if (intfd->bNumEndpoints < 1) - return NULL; - return get_endpoint(hostif, 0); -} - -/* * Creates an input endpoint. */ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi, @@ -569,7 +779,6 @@ snd_usb_midi_endpoint_t* rep) { snd_usb_midi_in_endpoint_t* ep; - struct usb_endpoint_descriptor* int_epd; void* buffer; unsigned int pipe; int length; @@ -580,17 +789,12 @@ return -ENOMEM; ep->umidi = umidi; - if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN) - int_epd = snd_usbmidi_get_midiman_int_epd(umidi); - else - int_epd = snd_usbmidi_get_int_epd(umidi); - ep->urb = usb_alloc_urb(0, GFP_KERNEL); if (!ep->urb) { snd_usbmidi_in_endpoint_delete(ep); return -ENOMEM; } - if (int_epd) + if (ep_info->in_interval) pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); else pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); @@ -600,10 +804,10 @@ snd_usbmidi_in_endpoint_delete(ep); return -ENOMEM; } - if (int_epd) + if (ep_info->in_interval) usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, length, snd_usb_complete_callback(snd_usbmidi_in_urb_complete), - ep, int_epd->bInterval); + ep, ep_info->in_interval); else usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length, snd_usb_complete_callback(snd_usbmidi_in_urb_complete), @@ -613,12 +817,12 @@ return 0; } -static int snd_usbmidi_count_bits(uint16_t x) +static unsigned int snd_usbmidi_count_bits(unsigned int x) { - int i, bits = 0; + unsigned int bits = 0; - for (i = 0; i < 16; ++i) - bits += (x & (1 << i)) != 0; + for (; x; x >>= 1) + bits += x & 1; return bits; } @@ -660,8 +864,9 @@ snd_usbmidi_out_endpoint_delete(ep); return -ENOMEM; } + /* we never use interrupt output pipes */ pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); - ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1) & ~3; + ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1); buffer = kmalloc(ep->max_transfer, GFP_KERNEL); if (!buffer) { snd_usbmidi_out_endpoint_delete(ep); @@ -680,6 +885,9 @@ ep->ports[i].cable = i << 4; } + if (umidi->usb_protocol_ops->init_out_endpoint) + umidi->usb_protocol_ops->init_out_endpoint(ep); + rep->out = ep; return 0; } @@ -712,8 +920,11 @@ 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->out && ep->out->urb) + if (ep->out && ep->out->urb) { usb_kill_urb(ep->out->urb); + if (umidi->usb_protocol_ops->finish_out_endpoint) + umidi->usb_protocol_ops->finish_out_endpoint(ep->out); + } if (ep->in && ep->in->urb) usb_kill_urb(ep->in->urb); } @@ -819,6 +1030,13 @@ /* M-Audio MidiSport 8x8 */ {0x0763, 0x1031, 8, "%s Control"}, {0x0763, 0x1033, 8, "%s Control"}, + /* MOTU Fastlane */ + {0x07fd, 0x0001, 0, "%s MIDI A"}, + {0x07fd, 0x0001, 1, "%s MIDI B"}, + /* Emagic Unitor8/AMT8/MT4 */ + {0x086a, 0x0001, 8, "%s Broadcast"}, + {0x086a, 0x0002, 8, "%s Broadcast"}, + {0x086a, 0x0003, 4, "%s Broadcast"}, }; static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, @@ -928,7 +1146,8 @@ for (i = 0; i < intfd->bNumEndpoints; ++i) { hostep = &hostif->endpoint[i]; ep = get_ep_desc(hostep); - if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK && + (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) continue; ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra; if (hostep->extralen < 4 || @@ -944,6 +1163,8 @@ } } endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) + endpoints[epidx].out_interval = ep->bInterval; endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); @@ -955,6 +1176,8 @@ } } endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) + endpoints[epidx].in_interval = ep->bInterval; endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); @@ -964,38 +1187,93 @@ } /* - * If the endpoints aren't specified, use the first bulk endpoints in the - * first alternate setting of the interface. + * On Roland devices, use the second alternate setting to be able to use + * the interrupt input endpoint. + */ +static void snd_usbmidi_switch_roland_altsetting(snd_usb_midi_t* umidi) +{ + struct usb_interface* intf; + struct usb_host_interface *hostif; + struct usb_interface_descriptor* intfd; + + intf = umidi->iface; + if (!intf || intf->num_altsetting != 2) + return; + + hostif = &intf->altsetting[1]; + intfd = get_iface_desc(hostif); + if (intfd->bNumEndpoints != 2 || + (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK || + (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) + return; + + snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n", + intfd->bAlternateSetting); + usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber, + intfd->bAlternateSetting); +} + +/* + * Try to find any usable endpoints in the interface. */ -static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, - snd_usb_midi_endpoint_info_t* endpoint) +static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi, + snd_usb_midi_endpoint_info_t* endpoint, + int max_endpoints) { struct usb_interface* intf; struct usb_host_interface *hostif; struct usb_interface_descriptor* intfd; struct usb_endpoint_descriptor* epd; - int i; + int i, out_eps = 0, in_eps = 0; + + if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582) + snd_usbmidi_switch_roland_altsetting(umidi); intf = umidi->iface; if (!intf || intf->num_altsetting < 1) return -ENOENT; - hostif = intf->altsetting; + hostif = intf->cur_altsetting; intfd = get_iface_desc(hostif); - if (intfd->bNumEndpoints < 1) - return -ENOENT; for (i = 0; i < intfd->bNumEndpoints; ++i) { epd = get_endpoint(hostif, i); - if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) + if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK && + (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) continue; - if (!endpoint->out_ep && endpoint->out_cables && - (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) - endpoint->out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if (!endpoint->in_ep && endpoint->in_cables && - (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) - endpoint->in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if (out_eps < max_endpoints && + (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { + endpoint[out_eps].out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) + endpoint[out_eps].out_interval = epd->bInterval; + ++out_eps; + } + if (in_eps < max_endpoints && + (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { + endpoint[in_eps].in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) + endpoint[in_eps].in_interval = epd->bInterval; + ++in_eps; + } } - return 0; + return (out_eps || in_eps) ? 0 : -ENOENT; +} + +/* + * Detects the endpoints for one-port-per-endpoint protocols. + */ +static int snd_usbmidi_detect_per_port_endpoints(snd_usb_midi_t* umidi, + snd_usb_midi_endpoint_info_t* endpoints) +{ + int err, i; + + err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS); + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { + if (endpoints[i].out_ep) + endpoints[i].out_cables = 0x0001; + if (endpoints[i].in_ep) + endpoints[i].in_cables = 0x0001; + } + return err; } /* @@ -1034,7 +1312,7 @@ if (!endpoint->in_cables && !endpoint->out_cables) return -ENOENT; - return snd_usbmidi_detect_endpoint(umidi, endpoint); + return snd_usbmidi_detect_endpoints(umidi, endpoint, 1); } /* @@ -1098,11 +1376,11 @@ return err; ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep_info.in_interval = get_endpoint(hostif, 0)->bInterval; ep_info.in_cables = endpoint->in_cables; err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); if (err < 0) return err; - umidi->endpoints[0].in->urb->complete = snd_usb_complete_callback(snd_usbmidi_in_midiman_complete); if (endpoint->out_cables > 0x0001) { ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; @@ -1203,6 +1481,7 @@ umidi->chip = chip; umidi->iface = iface; umidi->quirk = quirk; + umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; /* detect the endpoint(s) to use */ memset(endpoints, 0, sizeof(endpoints)); @@ -1213,15 +1492,30 @@ case QUIRK_MIDI_FIXED_ENDPOINT: memcpy(&endpoints[0], quirk->data, sizeof(snd_usb_midi_endpoint_info_t)); - err = snd_usbmidi_detect_endpoint(umidi, &endpoints[0]); + err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); break; case QUIRK_MIDI_YAMAHA: err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); break; case QUIRK_MIDI_MIDIMAN: + umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; memcpy(&endpoints[0], quirk->data, sizeof(snd_usb_midi_endpoint_info_t)); err = 0; + break; + case QUIRK_MIDI_NOVATION: + umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; + case QUIRK_MIDI_MOTU: + umidi->usb_protocol_ops = &snd_usbmidi_motu_ops; + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; + case QUIRK_MIDI_EMAGIC: + umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops; + memcpy(&endpoints[0], quirk->data, + sizeof(snd_usb_midi_endpoint_info_t)); + err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); break; default: snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); diff -Nru a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c --- a/sound/usb/usbmixer.c 2005-03-03 21:43:47 -08:00 +++ b/sound/usb/usbmixer.c 2005-03-03 21:43:47 -08:00 @@ -1519,7 +1519,7 @@ /* check the mapping table */ for (map = usbmix_ctl_maps; map->vendor; map++) { - if (map->vendor == le16_to_cpu(dev->idVendor) && map->product == le16_to_cpu(dev->idProduct)) { + if (map->vendor == state.vendor && map->product == state.product) { state.map = map->map; chip->ignore_ctl_error = map->ignore_ctl_error; break; diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h --- a/sound/usb/usbquirks.h 2005-03-03 21:43:47 -08:00 +++ b/sound/usb/usbquirks.h 2005-03-03 21:43:47 -08:00 @@ -72,6 +72,8 @@ YAMAHA_DEVICE(0x1008, "UX96"), YAMAHA_DEVICE(0x1009, "UX16"), YAMAHA_INTERFACE(0x100a, 3, "EOS BX"), +YAMAHA_DEVICE(0x100c, "UC-MX"), +YAMAHA_DEVICE(0x100d, "UC-KX"), YAMAHA_DEVICE(0x100e, "S08"), YAMAHA_DEVICE(0x100f, "CLP-150"), YAMAHA_DEVICE(0x1010, "CLP-170"), @@ -86,6 +88,7 @@ YAMAHA_DEVICE(0x101a, "CVP-210"), YAMAHA_DEVICE(0x101b, "PSR-1100"), YAMAHA_DEVICE(0x101c, "PSR-2100"), +YAMAHA_DEVICE(0x101d, "CLP-175"), YAMAHA_DEVICE(0x101e, "PSR-K1"), YAMAHA_DEVICE(0x1020, "EZ-250i"), YAMAHA_DEVICE(0x1021, "MOTIF ES 6"), @@ -125,9 +128,12 @@ YAMAHA_DEVICE(0x5006, "NHB32-C"), YAMAHA_DEVICE(0x5007, "DM1000"), YAMAHA_DEVICE(0x5008, "01V96"), +YAMAHA_DEVICE(0x5009, "SPX2000"), YAMAHA_DEVICE(0x500a, "PM5D"), YAMAHA_DEVICE(0x500b, "DME64N"), YAMAHA_DEVICE(0x500c, "DME24N"), +YAMAHA_DEVICE(0x500d, NULL), +YAMAHA_DEVICE(0x500e, NULL), YAMAHA_DEVICE(0x7000, "DTX"), YAMAHA_DEVICE(0x7010, "UB99"), #undef YAMAHA_DEVICE @@ -629,6 +635,19 @@ } }, { + USB_DEVICE(0x0582, 0x0042), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + .product_name = "RS-70", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, +{ USB_DEVICE(0x0582, 0x0044), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -685,19 +704,6 @@ } }, { - USB_DEVICE(0x0582, 0x0065), - .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { - .vendor_name = "EDIROL", - .product_name = "PCR-1", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0001, - .in_cables = 0x0003 - } - } -}, -{ /* * This quirk is for the "Advanced Driver" mode. If off, the UA-3FX * is standard compliant, but has only 16-bit PCM. @@ -732,6 +738,45 @@ .type = QUIRK_MIDI_STANDARD_INTERFACE } }, +{ + USB_DEVICE(0x0582, 0x0065), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "EDIROL", + .product_name = "PCR-1", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0003 + } + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + .product_name = "SP-606", + .ifnum = 3, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, +{ + USB_DEVICE(0x0582, 0x006d), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + .product_name = "FANTOM-X", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, { /* * This quirk is for the "Advanced" modes of the Edirol UA-25. * If the switch is not in an advanced setting, the UA-25 has @@ -763,6 +808,19 @@ } } }, +{ + USB_DEVICE(0x0582, 0x0075), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "BOSS", + .product_name = "DR-880", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, /* Midiman/M-Audio devices */ { @@ -876,6 +934,22 @@ * but captured samples are big-endian (see usbaudio.c). */ { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 3, + .type = QUIRK_IGNORE_INTERFACE + }, + { .ifnum = 4, .type = QUIRK_AUDIO_STANDARD_INTERFACE }, @@ -884,6 +958,10 @@ .type = QUIRK_AUDIO_STANDARD_INTERFACE }, { + .ifnum = 6, + .type = QUIRK_IGNORE_INTERFACE + }, + { .ifnum = 7, .type = QUIRK_AUDIO_STANDARD_INTERFACE }, @@ -936,27 +1014,81 @@ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "M-Audio", .product_name = "OmniStudio", - .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[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 3, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 4, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 5, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 6, + .type = QUIRK_IGNORE_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 + } } } }, /* Mark of the Unicorn devices */ { - /* thanks to Woodley Packard */ + /* thanks to Robert A. Lerche */ USB_DEVICE(0x07fd, 0x0001), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "MOTU", .product_name = "Fastlane", - .ifnum = 1, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0003, - .in_cables = 0x0003 + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = & (const snd_usb_audio_quirk_t[]) { + { + .ifnum = 0, + .type = QUIRK_MIDI_MOTU + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = -1 + } } } }, @@ -972,6 +1104,47 @@ }, +/* Emagic devices */ +{ + USB_DEVICE(0x086a, 0x0001), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Emagic", + /* .product_name = "Unitor8", */ + .ifnum = 2, + .type = QUIRK_MIDI_EMAGIC, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x80ff, + .in_cables = 0x80ff + } + } +}, +{ + USB_DEVICE(0x086a, 0x0002), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Emagic", + /* .product_name = "AMT8", */ + .ifnum = 2, + .type = QUIRK_MIDI_EMAGIC, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x80ff, + .in_cables = 0x80ff + } + } +}, +{ + USB_DEVICE(0x086a, 0x0003), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Emagic", + /* .product_name = "MT4", */ + .ifnum = 2, + .type = QUIRK_MIDI_EMAGIC, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x800f, + .in_cables = 0x8003 + } + } +}, + { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { @@ -979,6 +1152,35 @@ .product_name = "PHASE 26", .ifnum = 3, .type = QUIRK_MIDI_STANDARD_INTERFACE + } +}, + +/* Novation EMS devices */ +{ + USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Novation", + .product_name = "ReMOTE Audio/XStation", + .ifnum = 4, + .type = QUIRK_MIDI_NOVATION + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Novation", + .product_name = "Speedio", + .ifnum = 3, + .type = QUIRK_MIDI_NOVATION + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Novation", + .product_name = "ReMOTE25", + .ifnum = 0, + .type = QUIRK_MIDI_NOVATION } }, diff -Nru a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c --- a/sound/usb/usx2y/usbusx2yaudio.c 2005-03-03 21:43:47 -08:00 +++ b/sound/usb/usx2y/usbusx2yaudio.c 2005-03-03 21:43:47 -08:00 @@ -415,7 +415,6 @@ unsigned int pipe; int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; struct usb_device *dev = subs->usX2Y->chip.dev; - struct usb_host_endpoint *ep; pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint);