From e2374641a338cf7d22db4cfb871d6f5c70e40506 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 2 Apr 2005 20:31:02 +0200 Subject: [PATCH] --- yaml --- r: 2682 b: refs/heads/master c: b3d5496ea5915fa4848fe307af9f7097f312e932 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/CREDITS | 5 +- trunk/Documentation/i2c/writing-clients | 62 +- .../sound/alsa/ALSA-Configuration.txt | 127 +- trunk/Documentation/sound/alsa/CMIPCI.txt | 41 +- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 6 +- .../Documentation/sound/alsa/emu10k1-jack.txt | 74 - trunk/Documentation/sound/alsa/hdspm.txt | 362 -- trunk/Documentation/w1/w1.generic | 107 +- trunk/drivers/acorn/char/pcf8583.c | 3 - trunk/drivers/i2c/chips/isp1301_omap.c | 1 - trunk/drivers/i2c/chips/m41t00.c | 3 - trunk/drivers/i2c/chips/rtc8564.c | 3 - trunk/drivers/i2c/i2c-core.c | 35 - trunk/drivers/macintosh/therm_windtunnel.c | 6 +- trunk/drivers/media/video/adv7170.c | 6 - trunk/drivers/media/video/adv7175.c | 6 - trunk/drivers/media/video/bt819.c | 6 - trunk/drivers/media/video/bt832.c | 4 +- trunk/drivers/media/video/bt856.c | 6 - trunk/drivers/media/video/msp3400.c | 1 - trunk/drivers/media/video/saa5246a.c | 1 - trunk/drivers/media/video/saa5249.c | 1 - trunk/drivers/media/video/saa7110.c | 6 - trunk/drivers/media/video/saa7111.c | 6 - trunk/drivers/media/video/saa7114.c | 6 - trunk/drivers/media/video/saa7134/saa6752hs.c | 1 - trunk/drivers/media/video/saa7185.c | 6 - trunk/drivers/media/video/tda7432.c | 1 - trunk/drivers/media/video/tda9840.c | 1 - trunk/drivers/media/video/tda9875.c | 1 - trunk/drivers/media/video/tda9887.c | 1 - trunk/drivers/media/video/tea6415c.c | 1 - trunk/drivers/media/video/tea6420.c | 1 - trunk/drivers/media/video/tuner-3036.c | 13 +- trunk/drivers/media/video/tuner-core.c | 11 +- trunk/drivers/media/video/tvaudio.c | 1 - trunk/drivers/media/video/tveeprom.c | 1 - trunk/drivers/media/video/vpx3220.c | 6 - trunk/drivers/video/matrox/matroxfb_maven.c | 1 - trunk/drivers/w1/Kconfig | 16 +- trunk/drivers/w1/ds_w1_bridge.c | 4 +- trunk/drivers/w1/matrox_w1.c | 10 +- trunk/drivers/w1/w1.c | 546 +-- trunk/drivers/w1/w1.h | 113 +- trunk/drivers/w1/w1_family.c | 10 +- trunk/drivers/w1/w1_family.h | 18 +- trunk/drivers/w1/w1_int.c | 41 +- trunk/drivers/w1/w1_int.h | 6 +- trunk/drivers/w1/w1_io.c | 117 +- trunk/drivers/w1/w1_io.h | 9 +- trunk/drivers/w1/w1_log.h | 4 +- trunk/drivers/w1/w1_netlink.h | 4 +- trunk/drivers/w1/w1_smem.c | 50 +- trunk/drivers/w1/w1_therm.c | 100 +- trunk/include/linux/i2c.h | 12 - trunk/include/sound/ac97_codec.h | 8 +- trunk/include/sound/asound.h | 16 +- trunk/include/sound/control.h | 2 +- trunk/include/sound/emu10k1.h | 42 +- trunk/include/sound/gus.h | 23 + trunk/include/sound/hdspm.h | 131 - trunk/include/sound/pcm.h | 32 +- trunk/include/sound/seq_midi_event.h | 2 + trunk/include/sound/seq_virmidi.h | 1 + trunk/include/sound/timer.h | 2 + trunk/include/sound/version.h | 4 +- trunk/net/ipv4/Kconfig | 2 +- trunk/sound/Kconfig | 5 - trunk/sound/arm/Kconfig | 6 - trunk/sound/arm/Makefile | 3 - trunk/sound/arm/aaci.c | 968 ----- trunk/sound/arm/aaci.h | 246 -- trunk/sound/arm/devdma.c | 81 - trunk/sound/arm/devdma.h | 3 - trunk/sound/core/control.c | 4 +- trunk/sound/core/memalloc.c | 201 +- trunk/sound/core/oss/pcm_oss.c | 33 +- trunk/sound/core/oss/pcm_plugin.c | 5 +- trunk/sound/core/pcm.c | 3 +- trunk/sound/core/pcm_lib.c | 52 +- trunk/sound/core/pcm_memory.c | 1 - trunk/sound/core/pcm_misc.c | 16 + trunk/sound/core/pcm_native.c | 74 +- trunk/sound/core/seq/oss/seq_oss_synth.c | 24 +- trunk/sound/core/seq/seq_dummy.c | 5 +- trunk/sound/core/seq/seq_midi.c | 2 - trunk/sound/core/seq/seq_midi_event.c | 6 +- trunk/sound/core/seq/seq_queue.c | 3 +- trunk/sound/core/seq/seq_queue.h | 1 + trunk/sound/core/seq/seq_timer.c | 3 +- trunk/sound/core/seq/seq_timer.h | 2 + trunk/sound/core/seq/seq_virmidi.c | 8 +- trunk/sound/core/sound.c | 1 + trunk/sound/core/timer.c | 100 +- trunk/sound/core/timer_compat.c | 5 - trunk/sound/drivers/vx/vx_pcm.c | 12 +- trunk/sound/i2c/tea6330t.c | 3 +- trunk/sound/isa/Kconfig | 1 - trunk/sound/isa/ad1816a/ad1816a.c | 2 - trunk/sound/isa/cs423x/cs4236.c | 3 +- trunk/sound/isa/gus/gus_io.c | 14 +- trunk/sound/isa/gus/gus_main.c | 3 + trunk/sound/isa/gus/gus_mem.c | 12 +- trunk/sound/isa/gus/gus_pcm.c | 3 +- trunk/sound/isa/gus/gus_reset.c | 3 +- trunk/sound/isa/gus/gus_synth.c | 3 +- trunk/sound/isa/gus/gus_tables.h | 4 - trunk/sound/isa/gus/gus_volume.c | 8 - trunk/sound/pci/Kconfig | 13 - trunk/sound/pci/ac97/ac97_codec.c | 71 +- trunk/sound/pci/ac97/ac97_patch.c | 585 +-- trunk/sound/pci/ac97/ac97_patch.h | 1 - trunk/sound/pci/ali5451/ali5451.c | 283 +- trunk/sound/pci/als4000.c | 4 +- trunk/sound/pci/atiixp.c | 6 +- trunk/sound/pci/atiixp_modem.c | 42 +- trunk/sound/pci/au88x0/au88x0.c | 2 +- trunk/sound/pci/azt3328.c | 2 +- trunk/sound/pci/bt87x.c | 2 +- trunk/sound/pci/ca0106/ca0106.h | 70 +- trunk/sound/pci/ca0106/ca0106_main.c | 211 +- trunk/sound/pci/ca0106/ca0106_mixer.c | 76 +- trunk/sound/pci/ca0106/ca0106_proc.c | 31 +- trunk/sound/pci/cmipci.c | 159 +- trunk/sound/pci/cs4281.c | 10 +- trunk/sound/pci/cs46xx/cs46xx.c | 2 +- trunk/sound/pci/cs46xx/cs46xx_lib.c | 3 +- trunk/sound/pci/emu10k1/emu10k1.c | 2 +- trunk/sound/pci/emu10k1/emu10k1_main.c | 192 +- trunk/sound/pci/emu10k1/emu10k1x.c | 8 +- trunk/sound/pci/emu10k1/emufx.c | 56 +- trunk/sound/pci/emu10k1/emumixer.c | 14 +- trunk/sound/pci/emu10k1/emupcm.c | 6 +- trunk/sound/pci/emu10k1/emuproc.c | 89 +- trunk/sound/pci/emu10k1/irq.c | 46 +- trunk/sound/pci/emu10k1/p16v.c | 367 +- trunk/sound/pci/ens1370.c | 2 +- trunk/sound/pci/es1938.c | 2 +- trunk/sound/pci/es1968.c | 3 +- trunk/sound/pci/fm801.c | 3 +- trunk/sound/pci/hda/Makefile | 2 +- trunk/sound/pci/hda/hda_codec.c | 206 +- trunk/sound/pci/hda/hda_codec.h | 30 +- trunk/sound/pci/hda/hda_generic.c | 14 +- trunk/sound/pci/hda/hda_intel.c | 119 +- trunk/sound/pci/hda/hda_local.h | 37 +- trunk/sound/pci/hda/hda_patch.h | 3 - trunk/sound/pci/hda/hda_proc.c | 56 +- trunk/sound/pci/hda/patch_analog.c | 693 +--- trunk/sound/pci/hda/patch_cmedia.c | 216 +- trunk/sound/pci/hda/patch_realtek.c | 2787 ++++--------- trunk/sound/pci/hda/patch_sigmatel.c | 666 --- trunk/sound/pci/ice1712/amp.c | 30 - trunk/sound/pci/ice1712/amp.h | 16 +- trunk/sound/pci/ice1712/ice1712.c | 2 +- trunk/sound/pci/ice1712/ice1712.h | 5 - trunk/sound/pci/ice1712/ice1724.c | 2 +- trunk/sound/pci/ice1712/phase.c | 728 ---- trunk/sound/pci/ice1712/phase.h | 19 +- trunk/sound/pci/ice1712/vt1720_mobo.c | 9 - trunk/sound/pci/ice1712/vt1720_mobo.h | 4 +- trunk/sound/pci/intel8x0.c | 156 +- trunk/sound/pci/intel8x0m.c | 80 +- trunk/sound/pci/korg1212/korg1212.c | 2 +- trunk/sound/pci/maestro3.c | 222 +- trunk/sound/pci/mixart/mixart.c | 2 +- trunk/sound/pci/nm256/nm256.c | 2 +- trunk/sound/pci/rme32.c | 2 +- trunk/sound/pci/rme96.c | 2 +- trunk/sound/pci/rme9652/Makefile | 2 - trunk/sound/pci/rme9652/hdsp.c | 30 +- trunk/sound/pci/rme9652/hdspm.c | 3671 ----------------- trunk/sound/pci/rme9652/rme9652.c | 16 +- trunk/sound/pci/sonicvibes.c | 2 +- trunk/sound/pci/trident/trident.c | 5 +- trunk/sound/pci/via82xx.c | 145 +- trunk/sound/pci/via82xx_modem.c | 38 +- trunk/sound/pci/vx222/vx222.c | 2 +- trunk/sound/pci/ymfpci/ymfpci.c | 2 +- trunk/sound/pci/ymfpci/ymfpci_main.c | 35 +- trunk/sound/pcmcia/vx/vx_entry.c | 3 +- trunk/sound/synth/emux/emux_effect.c | 6 +- trunk/sound/usb/Kconfig | 1 - trunk/sound/usb/usbaudio.c | 308 +- trunk/sound/usb/usbaudio.h | 11 +- trunk/sound/usb/usbmidi.c | 128 +- trunk/sound/usb/usbmixer.c | 588 +-- trunk/sound/usb/usbmixer_maps.c | 126 +- trunk/sound/usb/usbquirks.h | 298 +- trunk/sound/usb/usx2y/usbusx2y.c | 2 +- trunk/sound/usb/usx2y/usbusx2yaudio.c | 6 +- 192 files changed, 3236 insertions(+), 14853 deletions(-) delete mode 100644 trunk/Documentation/sound/alsa/emu10k1-jack.txt delete mode 100644 trunk/Documentation/sound/alsa/hdspm.txt delete mode 100644 trunk/include/sound/hdspm.h delete mode 100644 trunk/sound/arm/aaci.c delete mode 100644 trunk/sound/arm/aaci.h delete mode 100644 trunk/sound/arm/devdma.c delete mode 100644 trunk/sound/arm/devdma.h delete mode 100644 trunk/sound/pci/hda/patch_sigmatel.c delete mode 100644 trunk/sound/pci/rme9652/hdspm.c diff --git a/[refs] b/[refs] index bb76200cbd9d..4e69caa84442 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a0cd30fd26a398c0c6e50c6760610d4529f17a84 +refs/heads/master: b3d5496ea5915fa4848fe307af9f7097f312e932 diff --git a/trunk/CREDITS b/trunk/CREDITS index 3b7a1548aaf9..2993348ce6ce 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -2380,10 +2380,9 @@ E: tmolina@cablespeed.com D: bug fixes, documentation, minor hackery N: James Morris -E: jmorris@redhat.com +E: jmorris@intercode.com.au W: http://www.intercode.com.au/jmorris/ -D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec, -D: Crypto API, general networking, miscellaneous. +D: Netfilter, Linux Security Modules (LSM). S: PO Box 707 S: Spit Junction NSW 2088 S: Australia diff --git a/trunk/Documentation/i2c/writing-clients b/trunk/Documentation/i2c/writing-clients index ad27511e3c7d..f482dae81de3 100644 --- a/trunk/Documentation/i2c/writing-clients +++ b/trunk/Documentation/i2c/writing-clients @@ -171,45 +171,31 @@ The following lists are used internally: normal_i2c: filled in by the module writer. A list of I2C addresses which should normally be examined. - normal_i2c_range: filled in by the module writer. - A list of pairs of I2C addresses, each pair being an inclusive range of - addresses which should normally be examined. probe: insmod parameter. A list of pairs. The first value is a bus number (-1 for any I2C bus), the second is the address. These addresses are also probed, as if they were in the 'normal' list. - probe_range: insmod parameter. - A list of triples. The first value is a bus number (-1 for any I2C bus), - the second and third are addresses. These form an inclusive range of - addresses that are also probed, as if they were in the 'normal' list. ignore: insmod parameter. A list of pairs. The first value is a bus number (-1 for any I2C bus), the second is the I2C address. These addresses are never probed. This parameter overrules 'normal' and 'probe', but not the 'force' lists. - ignore_range: insmod parameter. - A list of triples. The first value is a bus number (-1 for any I2C bus), - the second and third are addresses. These form an inclusive range of - I2C addresses that are never probed. - This parameter overrules 'normal' and 'probe', but not the 'force' lists. force: insmod parameter. A list of pairs. The first value is a bus number (-1 for any I2C bus), the second is the I2C address. A device is blindly assumed to be on the given address, no probing is done. -Fortunately, as a module writer, you just have to define the `normal' -and/or `normal_range' parameters. The complete declaration could look -like this: +Fortunately, as a module writer, you just have to define the `normal_i2c' +parameter. The complete declaration could look like this: - /* Scan 0x20 to 0x2f, 0x37, and 0x40 to 0x4f */ - static unsigned short normal_i2c[] = { 0x37,I2C_CLIENT_END }; - static unsigned short normal_i2c_range[] = { 0x20, 0x2f, 0x40, 0x4f, - I2C_CLIENT_END }; + /* Scan 0x37, and 0x48 to 0x4f */ + static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; /* Magic definition of all other variables and things */ I2C_CLIENT_INSMOD; -Note that you *have* to call the two defined variables `normal_i2c' and -`normal_i2c_range', without any prefix! +Note that you *have* to call the defined variable `normal_i2c', +without any prefix! Probing classes (sensors) @@ -223,39 +209,17 @@ The following lists are used internally. They are all lists of integers. normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END. A list of I2C addresses which should normally be examined. - normal_i2c_range: filled in by the module writer. Terminated by - SENSORS_I2C_END - A list of pairs of I2C addresses, each pair being an inclusive range of - addresses which should normally be examined. normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END. A list of ISA addresses which should normally be examined. - normal_isa_range: filled in by the module writer. Terminated by - SENSORS_ISA_END - A list of triples. The first two elements are ISA addresses, being an - range of addresses which should normally be examined. The third is the - modulo parameter: only addresses which are 0 module this value relative - to the first address of the range are actually considered. probe: insmod parameter. Initialize this list with SENSORS_I2C_END values. A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for the ISA bus, -1 for any I2C bus), the second is the address. These addresses are also probed, as if they were in the 'normal' list. - probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END - values. - A list of triples. The first value is a bus number (SENSORS_ISA_BUS for - the ISA bus, -1 for any I2C bus), the second and third are addresses. - These form an inclusive range of addresses that are also probed, as - if they were in the 'normal' list. ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values. A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for the ISA bus, -1 for any I2C bus), the second is the I2C address. These addresses are never probed. This parameter overrules 'normal' and 'probe', but not the 'force' lists. - ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END - values. - A list of triples. The first value is a bus number (SENSORS_ISA_BUS for - the ISA bus, -1 for any I2C bus), the second and third are addresses. - These form an inclusive range of I2C addresses that are never probed. - This parameter overrules 'normal' and 'probe', but not the 'force' lists. Also used is a list of pointers to sensors_force_data structures: force_data: insmod parameters. A list, ending with an element of which @@ -269,16 +233,14 @@ Also used is a list of pointers to sensors_force_data structures: So we have a generic insmod variabled `force', and chip-specific variables `force_CHIPNAME'. -Fortunately, as a module writer, you just have to define the `normal' -and/or `normal_range' parameters, and define what chip names are used. +Fortunately, as a module writer, you just have to define the `normal_i2c' +and `normal_isa' parameters, and define what chip names are used. The complete declaration could look like this: - /* Scan i2c addresses 0x20 to 0x2f, 0x37, and 0x40 to 0x4f - static unsigned short normal_i2c[] = {0x37,SENSORS_I2C_END}; - static unsigned short normal_i2c_range[] = {0x20,0x2f,0x40,0x4f, - SENSORS_I2C_END}; + /* Scan i2c addresses 0x37, and 0x48 to 0x4f */ + static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; /* Scan ISA address 0x290 */ static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END}; - static unsigned int normal_isa_range[] = {SENSORS_ISA_END}; /* Define chips foo and bar, as well as all module parameters and things */ SENSORS_INSMOD_2(foo,bar); diff --git a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt index 104a994b8289..71ef0498d5e0 100644 --- a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt @@ -615,11 +615,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-hda-intel -------------------- - Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450, - VIA VT8251/VT8237A + Module for Intel HD Audio (ICH6, ICH6M, ICH7) model - force the model name - position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF) Module supports up to 8 cards. @@ -637,10 +635,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 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 - z71v 3-jack (HP shared SPDIF) - asus 3-jack - uniwill 3-jack - F1734 2-jack CMI9880 minimal 3-jack in back @@ -648,15 +642,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 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 - auto auto-config reading BIOS (default) - - Note 2: If you get click noises on output, try the module option - position_fix=1 or 2. position_fix=1 will use the SD_LPIB - register value without FIFO size correction as the current - DMA pointer. position_fix=2 will make the driver to use - the position buffer instead of reading SD_LPIB register. - (Usually SD_LPLIB register is more accurate than the - position buffer.) Module snd-hdsp --------------- @@ -675,19 +660,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. module did formerly. It will allocate the buffers in advance when any HDSP cards are found. To make the buffer allocation sure, load snd-page-alloc module in the early - stage of boot sequence. See "Early Buffer Allocation" - section. - - Module snd-hdspm - ---------------- - - Module for RME HDSP MADI board. - - precise_ptr - Enable precise pointer, or disable. - line_outs_monitor - Send playback streams to analog outs by default. - enable_monitor - Enable Analog Out on Channel 63/64 by default. - - See hdspm.txt for details. + stage of boot sequence. Module snd-ice1712 ------------------ @@ -704,19 +677,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. * TerraTec EWS 88D * TerraTec EWX 24/96 * TerraTec DMX 6Fire - * TerraTec Phase 88 * Hoontech SoundTrack DSP 24 * Hoontech SoundTrack DSP 24 Value * Hoontech SoundTrack DSP 24 Media 7.1 - * Event Electronics, EZ8 * Digigram VX442 - * Lionstracs, Mediastaton model - Use the given board model, one of the following: delta1010, dio2496, delta66, delta44, audiophile, delta410, delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d, - dmx6fire, dsp24, dsp24_value, dsp24_71, ez8, - phase88, mediastation + dmx6fire, dsp24, dsp24_value, dsp24_71, ez8 omni - Omni I/O support for MidiMan M-Audio Delta44/66 cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever) in msec resolution, default value is 500 (0.5 sec) @@ -725,46 +694,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. is not used with all Envy24 based cards (for example in the MidiMan Delta serie). - Note: The supported board is detected by reading EEPROM or PCI - SSID (if EEPROM isn't available). You can override the - model by passing "model" module option in case that the - driver isn't configured properly or you want to try another - type for testing. - Module snd-ice1724 ------------------ - Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards. + Module for Envy24HT (VT/ICE1724) based PCI sound cards. * MidiMan M Audio Revolution 7.1 * AMP Ltd AUDIO2000 - * TerraTec Aureon 5.1 Sky - * TerraTec Aureon 7.1 Space - * TerraTec Aureon 7.1 Universe - * TerraTec Phase 22 - * TerraTec Phase 28 - * AudioTrak Prodigy 7.1 - * AudioTrak Prodigy 192 - * Pontis MS300 - * Albatron K8X800 Pro II - * Chaintech ZNF3-150 - * Chaintech ZNF3-250 - * Chaintech 9CJS - * Chaintech AV-710 - * Shuttle SN25P + * TerraTec Aureon Sky-5.1, Space-7.1 model - Use the given board model, one of the following: - revo71, amp2000, prodigy71, prodigy192, aureon51, - aureon71, universe, k8x800, phase22, phase28, ms300, - av710 + revo71, amp2000, prodigy71, aureon51, aureon71, + k8x800 Module supports up to 8 cards and autoprobe. - Note: The supported board is detected by reading EEPROM or PCI - SSID (if EEPROM isn't available). You can override the - model by passing "model" module option in case that the - driver isn't configured properly or you want to try another - type for testing. - Module snd-intel8x0 ------------------- @@ -1083,8 +1026,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. module did formerly. It will allocate the buffers in advance when any RME9652 cards are found. To make the buffer allocation sure, load snd-page-alloc module in the early - stage of boot sequence. See "Early Buffer Allocation" - section. + stage of boot sequence. Module snd-sa11xx-uda1341 (on arm only) --------------------------------------- @@ -1269,18 +1211,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ------------------ Module for AC'97 motherboards based on VIA 82C686A/686B, 8233, - 8233A, 8233C, 8235, 8237 (south) bridge. + 8233A, 8233C, 8235 (south) bridge. mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup [VIA686A/686B only] joystick - Enable joystick (default off) [VIA686A/686B only] ac97_clock - AC'97 codec clock base (default 48000Hz) dxs_support - support DXS channels, - 0 = auto (default), 1 = enable, 2 = disable, - 3 = 48k only, 4 = no VRA, 5 = enable any sample - rate and different sample rates on different - channels - [VIA8233/C, 8235, 8237 only] + 0 = auto (defalut), 1 = enable, 2 = disable, + 3 = 48k only, 4 = no VRA + [VIA8233/C,8235 only] ac97_quirk - AC'97 workaround for strange hardware See the description of intel8x0 module for details. @@ -1292,23 +1232,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. default value 1.4. Then the interrupt number will be assigned under 15. You might also upgrade your BIOS. - Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound) + Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound) channels as the first PCM. On these channels, up to 4 - streams can be played at the same time, and the controller - can perform sample rate conversion with separate rates for - each channel. + streams can be played at the same time. As default (dxs_support = 0), 48k fixed rate is chosen except for the known devices since the output is often noisy except for 48k on some mother boards due to the bug of BIOS. - Please try once dxs_support=5 and if it works on other + Please try once dxs_support=1 and if it works on other sample rates (e.g. 44.1kHz of mp3 playback), please let us know the PCI subsystem vendor/device id's (output of "lspci -nv"). - If dxs_support=5 does not work, try dxs_support=4; if it - doesn't work too, try dxs_support=1. (dxs_support=1 is - usually for old motherboards. The correct implementated - board should work with 4 or 5.) If it still doesn't + If it doesn't work, try dxs_support=4. If it still doesn't work and the default setting is ok, dxs_support=3 is the right choice. If the default setting doesn't work at all, try dxs_support=2 to disable the DXS channels. @@ -1562,36 +1497,6 @@ Proc interfaces (/proc/asound) echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss -Early Buffer Allocation -======================= - -Some drivers (e.g. hdsp) require the large contiguous buffers, and -sometimes it's too late to find such spaces when the driver module is -actually loaded due to memory fragmentation. You can pre-allocate the -PCM buffers by loading snd-page-alloc module and write commands to its -proc file in prior, for example, in the early boot stage like -/etc/init.d/*.local scripts. - -Reading the proc file /proc/drivers/snd-page-alloc shows the current -usage of page allocation. In writing, you can send the following -commands to the snd-page-alloc driver: - - - add VENDOR DEVICE MASK SIZE BUFFERS - - VENDOR and DEVICE are PCI vendor and device IDs. They take - integer numbers (0x prefix is needed for the hex). - MASK is the PCI DMA mask. Pass 0 if not restricted. - SIZE is the size of each buffer to allocate. You can pass - k and m suffix for KB and MB. The max number is 16MB. - BUFFERS is the number of buffers to allocate. It must be greater - than 0. The max number is 4. - - - erase - - This will erase the all pre-allocated buffers which are not in - use. - - Links ===== diff --git a/trunk/Documentation/sound/alsa/CMIPCI.txt b/trunk/Documentation/sound/alsa/CMIPCI.txt index 1872e24442a4..4a7df771b806 100644 --- a/trunk/Documentation/sound/alsa/CMIPCI.txt +++ b/trunk/Documentation/sound/alsa/CMIPCI.txt @@ -89,22 +89,19 @@ and use the interleaved 4 channel data. There are some control switchs affecting to the speaker connections: -"Line-In Mode" - an enum control to change the behavior of line-in - jack. Either "Line-In", "Rear Output" or "Bass Output" can - be selected. The last item is available only with model 039 - or newer. - When "Rear Output" is chosen, the surround channels 3 and 4 - are output to line-in jack. -"Mic-In Mode" - an enum control to change the behavior of mic-in - jack. Either "Mic-In" or "Center/LFE Output" can be - selected. - When "Center/LFE Output" is chosen, the center and bass - channels (channels 5 and 6) are output to mic-in jack. +"Line-In As Rear" - As mentioned above, the line-in jack is used + for the rear (3th and 4th channels) output. +"Line-In As Bass" - The line-in jack is used for the bass (5th + and 6th channels) output. +"Mic As Center/LFE" - The mic jack is used for the bass output. + If this switch is on, you cannot use a microphone as a capture + source, of course. + Digital I/O ----------- -The CM8x38 provides the excellent SPDIF capability with very cheap +The CM8x38 provides the excellent SPDIF capability with very chip price (yes, that's the reason I bought the card :) The SPDIF playback and capture are done via the third PCM device @@ -125,9 +122,8 @@ respectively, so you cannot playback both analog and digital streams simultaneously. To enable SPDIF output, you need to turn on "IEC958 Output Switch" -control via mixer or alsactl ("IEC958" is the official name of -so-called S/PDIF). Then you'll see the red light on from the card so -you know that's working obviously :) +control via mixer or alsactl. Then you'll see the red light on from +the card so you know that's working obviously :) The SPDIF input is always enabled, so you can hear SPDIF input data from line-out with "IEC958 In Monitor" switch at any time (see below). @@ -209,10 +205,9 @@ In addition to the standard SB mixer, CM8x38 provides more functions. MIDI CONTROLLER --------------- -The MPU401-UART interface is disabled as default. You need to set -module option "mpu_port" with a valid I/O port address to enable the -MIDI support. The valid I/O ports are 0x300, 0x310, 0x320 and 0x330. -Choose the value which doesn't conflict with other cards. +The MPU401-UART interface is enabled as default only for the first +(CMIPCI) card. You need to set module option "midi_port" properly +for the 2nd (CMIPCI) card. There is _no_ hardware wavetable function on this chip (except for OPL3 synth below). @@ -234,11 +229,9 @@ I don't know why.. Joystick and Modem ------------------ -The legacy joystick is supported. To enable the joystick support, pass -joystick_port=1 module option. The value 1 means the auto-detection. -If the auto-detection fails, try to pass the exact I/O address. - -The modem is enabled dynamically via a card control switch "Modem". +The joystick and modem should be available by enabling the control +switch "Joystick" and "Modem" respectively. But I myself have never +tested them yet. Debugging Information diff --git a/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index db0b7d2dc477..e789475304b6 100644 --- a/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -371,7 +371,7 @@ create probe() callback. create remove() callback. create pci_driver table which contains the three pointers above. - create init() function just calling pci_register_driver() to register the pci_driver table defined above. + create init() function just calling pci_module_init() to register the pci_driver table defined above. create exit() function to call pci_unregister_driver() function. @@ -1198,7 +1198,7 @@ /* initialization of the module */ static int __init alsa_card_mychip_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } /* clean up the module */ @@ -1654,7 +1654,7 @@ - - - Here as a first value the channel-index is taken to get/set the - corresponding mixer channel, where 0-63 are the input to output - fader and 64-127 the playback to outputs fader. Value 0 - is channel muted 0 and 32768 an amplification of 1. - - Chn 1-64 - - fast mixer for the ALSA-mixer utils. The diagonal of the - mixer-matrix is implemented from playback to output. - - - Line Out - - Name -- "Line Out" - - Access -- Read Write - - Values -- 0 1 - - Switching on and off the analog out, which has nothing to do - with mixing or routing. the analog outs reflects channel 63,64. - - ---- information (only read access): - - Sample Rate - - Name -- "System Sample Rate" - - Access -- Read-only - - getting the sample rate. - - - External Rate measured - - Name -- "External Rate" - - Access -- Read only - - - Should be "Autosync Rate", but Name used is - ALSA-Scheme. External Sample frequency liked used on Autosync is - reported. - - - MADI Sync Status - - Name -- "MADI Sync Lock Status" - - Access -- Read - - Values -- 0,1,2 - - MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced. - - - Word Clock Sync Status - - Name -- "Word Clock Lock Status" - - Access -- Read - - Values -- 0,1,2 - - Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced. - - AutoSync - - Name -- "AutoSync Reference" - - Access -- Read - - Values -- "WordClock", "MADI", "None" - - Sync-Reference is either "WordClock", "MADI" or none. - - RX 64ch --- noch nicht implementiert - - MADI-Receiver is in 64 channel mode oder 56 channel mode. - - - AB_inp --- not tested - - Used input for Auto-Input. - - - actual Buffer Position --- not implemented - - !!! this is a ALSA internal function, so no control is used !!! - - - -Calling Parameter: - - index int array (min = 1, max = 8), - "Index value for RME HDSPM interface." card-index within ALSA - - note: ALSA-standard - - id string array (min = 1, max = 8), - "ID string for RME HDSPM interface." - - note: ALSA-standard - - enable int array (min = 1, max = 8), - "Enable/disable specific HDSPM sound-cards." - - note: ALSA-standard - - precise_ptr int array (min = 1, max = 8), - "Enable precise pointer, or disable." - - note: Use only when the application supports this (which is a special case). - - line_outs_monitor int array (min = 1, max = 8), - "Send playback streams to analog outs by default." - - - note: each playback channel is mixed to the same numbered output - channel (routed). This is against the ALSA-convention, where all - channels have to be muted on after loading the driver, but was - used before on other cards, so i historically use it again) - - - - enable_monitor int array (min = 1, max = 8), - "Enable Analog Out on Channel 63/64 by default." - - note: here the analog output is enabled (but not routed). \ No newline at end of file diff --git a/trunk/Documentation/w1/w1.generic b/trunk/Documentation/w1/w1.generic index f937fbe1cacb..eace3046a858 100644 --- a/trunk/Documentation/w1/w1.generic +++ b/trunk/Documentation/w1/w1.generic @@ -1,92 +1,19 @@ -The 1-wire (w1) subsystem ------------------------------------------------------------------- -The 1-wire bus is a simple master-slave bus that communicates via a single -signal wire (plus ground, so two wires). - -Devices communicate on the bus by pulling the signal to ground via an open -drain output and by sampling the logic level of the signal line. - -The w1 subsystem provides the framework for managing w1 masters and -communication with slaves. - -All w1 slave devices must be connected to a w1 bus master device. - -Example w1 master devices: - DS9490 usb device - W1-over-GPIO - DS2482 (i2c to w1 bridge) - Emulated devices, such as a RS232 converter, parallel port adapter, etc - - -What does the w1 subsystem do? ------------------------------------------------------------------- -When a w1 master driver registers with the w1 subsystem, the following occurs: - - - sysfs entries for that w1 master are created - - the w1 bus is periodically searched for new slave devices - -When a device is found on the bus, w1 core checks if driver for it's family is -loaded. If so, the family driver is attached to the slave. -If there is no driver for the family, a simple sysfs entry is created -for the slave device. - - -W1 device families ------------------------------------------------------------------- -Slave devices are handled by a driver written for a family of w1 devices. - -A family driver populates a struct w1_family_ops (see w1_family.h) and -registers with the w1 subsystem. - -Current family drivers: -w1_therm - (ds18?20 thermal sensor family driver) - provides temperature reading function which is bound to ->rbin() method - of the above w1_family_ops structure. - -w1_smem - driver for simple 64bit memory cell provides ID reading method. +Any w1 device must be connected to w1 bus master device - for example +ds9490 usb device or w1-over-GPIO or RS232 converter. +Driver for w1 bus master must provide several functions(you can find +them in struct w1_bus_master definition in w1.h) which then will be +called by w1 core to send various commands over w1 bus(by default it is +reset and search commands). When some device is found on the bus, w1 core +checks if driver for it's family is loaded. +If driver is loaded w1 core creates new w1_slave object and registers it +in the system(creates some generic sysfs files(struct w1_family_ops in +w1_family.h), notifies any registered listener and so on...). +It is device driver's business to provide any communication method +upstream. +For example w1_therm driver(ds18?20 thermal sensor family driver) +provides temperature reading function which is bound to ->rbin() method +of the above w1_family_ops structure. +w1_smem - driver for simple 64bit memory cell provides ID reading +method. You can call above methods by reading appropriate sysfs files. - - -What does a w1 master driver need to implement? ------------------------------------------------------------------- - -The driver for w1 bus master must provide at minimum two functions. - -Emulated devices must provide the ability to set the output signal level -(write_bit) and sample the signal level (read_bit). - -Devices that support the 1-wire natively must provide the ability to write and -sample a bit (touch_bit) and reset the bus (reset_bus). - -Most hardware provides higher-level functions that offload w1 handling. -See struct w1_bus_master definition in w1.h for details. - - -w1 master sysfs interface ------------------------------------------------------------------- - - a directory for a found device. The format is family-serial -bus - (standard) symlink to the w1 bus -driver - (standard) symlink to the w1 driver -w1_master_attempts - the number of times a search was attempted -w1_master_max_slave_count - - the maximum slaves that may be attached to a master -w1_master_name - the name of the device (w1_bus_masterX) -w1_master_search - the number of searches left to do, -1=continual (default) -w1_master_slave_count - - the number of slaves found -w1_master_slaves - the names of the slaves, one per line -w1_master_timeout - the delay in seconds between searches - -If you have a w1 bus that never changes (you don't add or remove devices), -you can set w1_master_search to a positive value to disable searches. - - -w1 slave sysfs interface ------------------------------------------------------------------- -bus - (standard) symlink to the w1 bus -driver - (standard) symlink to the w1 driver -name - the device name, usually the same as the directory name -w1_slave - (optional) a binary file whose meaning depends on the - family driver - diff --git a/trunk/drivers/acorn/char/pcf8583.c b/trunk/drivers/acorn/char/pcf8583.c index ad7ae7ab8920..141b4c237a50 100644 --- a/trunk/drivers/acorn/char/pcf8583.c +++ b/trunk/drivers/acorn/char/pcf8583.c @@ -26,11 +26,8 @@ static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, - .normal_i2c_range = ignore, .probe = ignore, - .probe_range = ignore, .ignore = ignore, - .ignore_range = ignore, .force = ignore, }; diff --git a/trunk/drivers/i2c/chips/isp1301_omap.c b/trunk/drivers/i2c/chips/isp1301_omap.c index 7f29a8aff165..354a26295672 100644 --- a/trunk/drivers/i2c/chips/isp1301_omap.c +++ b/trunk/drivers/i2c/chips/isp1301_omap.c @@ -145,7 +145,6 @@ static inline void notresponding(struct isp1301 *isp) static unsigned short normal_i2c[] = { ISP_BASE, ISP_BASE + 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/i2c/chips/m41t00.c b/trunk/drivers/i2c/chips/m41t00.c index e771566dffa8..5e463c47bfbc 100644 --- a/trunk/drivers/i2c/chips/m41t00.c +++ b/trunk/drivers/i2c/chips/m41t00.c @@ -40,11 +40,8 @@ static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, - .normal_i2c_range = ignore, .probe = ignore, - .probe_range = ignore, .ignore = ignore, - .ignore_range = ignore, .force = ignore, }; diff --git a/trunk/drivers/i2c/chips/rtc8564.c b/trunk/drivers/i2c/chips/rtc8564.c index 5a9deddb626b..30f553e73700 100644 --- a/trunk/drivers/i2c/chips/rtc8564.c +++ b/trunk/drivers/i2c/chips/rtc8564.c @@ -66,11 +66,8 @@ static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, - .normal_i2c_range = ignore, .probe = ignore, - .probe_range = ignore, .ignore = ignore, - .ignore_range = ignore, .force = ignore, }; diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index a22e53badacb..4cc8c9f7211c 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -742,18 +742,6 @@ int i2c_probe(struct i2c_adapter *adapter, found = 1; } } - for (i = 0; - !found && (address_data->ignore_range[i] != I2C_CLIENT_END); - i += 3) { - if (((adap_id == address_data->ignore_range[i]) || - ((address_data->ignore_range[i]==ANY_I2C_BUS))) && - (addr >= address_data->ignore_range[i+1]) && - (addr <= address_data->ignore_range[i+2])) { - dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, " - "addr %04x\n", adap_id,addr); - found = 1; - } - } if (found) continue; @@ -769,17 +757,6 @@ int i2c_probe(struct i2c_adapter *adapter, } } - for (i = 0; - !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END); - i += 2) { - if ((addr >= address_data->normal_i2c_range[i]) && - (addr <= address_data->normal_i2c_range[i+1])) { - found = 1; - dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, " - "addr %04x\n", adap_id,addr); - } - } - for (i = 0; !found && (address_data->probe[i] != I2C_CLIENT_END); i += 2) { @@ -791,18 +768,6 @@ int i2c_probe(struct i2c_adapter *adapter, "addr %04x\n", adap_id,addr); } } - for (i = 0; - !found && (address_data->probe_range[i] != I2C_CLIENT_END); - i += 3) { - if (((adap_id == address_data->probe_range[i]) || - (address_data->probe_range[i] == ANY_I2C_BUS)) && - (addr >= address_data->probe_range[i+1]) && - (addr <= address_data->probe_range[i+2])) { - found = 1; - dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, " - "addr %04x\n", adap_id,addr); - } - } if (!found) continue; diff --git a/trunk/drivers/macintosh/therm_windtunnel.c b/trunk/drivers/macintosh/therm_windtunnel.c index 0bdb47f08c2a..61400f04015e 100644 --- a/trunk/drivers/macintosh/therm_windtunnel.c +++ b/trunk/drivers/macintosh/therm_windtunnel.c @@ -51,8 +51,10 @@ static int do_probe( struct i2c_adapter *adapter, int addr, int kind); /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */ -static unsigned short normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, + 0x2c, 0x2d, 0x2e, 0x2f, + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/media/video/adv7170.c b/trunk/drivers/media/video/adv7170.c index 80254caa444c..e9bf3394296a 100644 --- a/trunk/drivers/media/video/adv7170.c +++ b/trunk/drivers/media/video/adv7170.c @@ -384,21 +384,15 @@ static unsigned short normal_i2c[] = I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/adv7175.c b/trunk/drivers/media/video/adv7175.c index 95d0974b0ab5..2d5fa44fcd4d 100644 --- a/trunk/drivers/media/video/adv7175.c +++ b/trunk/drivers/media/video/adv7175.c @@ -434,21 +434,15 @@ static unsigned short normal_i2c[] = I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/bt819.c b/trunk/drivers/media/video/bt819.c index cf0db2554a80..31d51851bb44 100644 --- a/trunk/drivers/media/video/bt819.c +++ b/trunk/drivers/media/video/bt819.c @@ -500,21 +500,15 @@ static unsigned short normal_i2c[] = { I2C_BT819 >> 1, I2C_CLIENT_END, }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/bt832.c b/trunk/drivers/media/video/bt832.c index efe605a113a1..07f72f64c5f7 100644 --- a/trunk/drivers/media/video/bt832.c +++ b/trunk/drivers/media/video/bt832.c @@ -39,8 +39,8 @@ MODULE_LICENSE("GPL"); /* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_BT832_ALT1>>1,I2C_BT832_ALT2>>1,I2C_CLIENT_END}; +static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; /* ---------------------------------------------------------------------- */ diff --git a/trunk/drivers/media/video/bt856.c b/trunk/drivers/media/video/bt856.c index 72c7eb0f8c24..59121a0ec816 100644 --- a/trunk/drivers/media/video/bt856.c +++ b/trunk/drivers/media/video/bt856.c @@ -288,21 +288,15 @@ bt856_command (struct i2c_client *client, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/msp3400.c b/trunk/drivers/media/video/msp3400.c index 7fbb8581a87d..09464d624a6b 100644 --- a/trunk/drivers/media/video/msp3400.c +++ b/trunk/drivers/media/video/msp3400.c @@ -147,7 +147,6 @@ static unsigned short normal_i2c[] = { I2C_MSP3400C_ALT >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ diff --git a/trunk/drivers/media/video/saa5246a.c b/trunk/drivers/media/video/saa5246a.c index ba69f09cbdd1..b8054da31ffd 100644 --- a/trunk/drivers/media/video/saa5246a.c +++ b/trunk/drivers/media/video/saa5246a.c @@ -64,7 +64,6 @@ static struct video_device saa_template; /* Declared near bottom */ /* Addresses to scan */ static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; static struct i2c_client client_template; diff --git a/trunk/drivers/media/video/saa5249.c b/trunk/drivers/media/video/saa5249.c index d74caa139f0a..7ffa2e9a9bf3 100644 --- a/trunk/drivers/media/video/saa5249.c +++ b/trunk/drivers/media/video/saa5249.c @@ -132,7 +132,6 @@ static struct video_device saa_template; /* Declared near bottom */ /* Addresses to scan */ static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; I2C_CLIENT_INSMOD; static struct i2c_client client_template; diff --git a/trunk/drivers/media/video/saa7110.c b/trunk/drivers/media/video/saa7110.c index 64273b438530..90b0a0b34f38 100644 --- a/trunk/drivers/media/video/saa7110.c +++ b/trunk/drivers/media/video/saa7110.c @@ -463,21 +463,15 @@ static unsigned short normal_i2c[] = { (I2C_SAA7110 >> 1) + 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/saa7111.c b/trunk/drivers/media/video/saa7111.c index 0a873112ae23..e305a89f7cd7 100644 --- a/trunk/drivers/media/video/saa7111.c +++ b/trunk/drivers/media/video/saa7111.c @@ -482,21 +482,15 @@ saa7111_command (struct i2c_client *client, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/saa7114.c b/trunk/drivers/media/video/saa7114.c index e73023695e58..1ca4e70fed76 100644 --- a/trunk/drivers/media/video/saa7114.c +++ b/trunk/drivers/media/video/saa7114.c @@ -820,21 +820,15 @@ saa7114_command (struct i2c_client *client, */ static unsigned short normal_i2c[] = { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/saa7134/saa6752hs.c b/trunk/drivers/media/video/saa7134/saa6752hs.c index 1db022682980..42c2b565c9fe 100644 --- a/trunk/drivers/media/video/saa7134/saa6752hs.c +++ b/trunk/drivers/media/video/saa7134/saa6752hs.c @@ -22,7 +22,6 @@ /* Addresses to scan */ static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; I2C_CLIENT_INSMOD; MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); diff --git a/trunk/drivers/media/video/saa7185.c b/trunk/drivers/media/video/saa7185.c index 5f0b224c3cb6..5c623fadc8fe 100644 --- a/trunk/drivers/media/video/saa7185.c +++ b/trunk/drivers/media/video/saa7185.c @@ -380,21 +380,15 @@ saa7185_command (struct i2c_client *client, * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/media/video/tda7432.c b/trunk/drivers/media/video/tda7432.c index 376a4a439e9b..07ba6d3ed08c 100644 --- a/trunk/drivers/media/video/tda7432.c +++ b/trunk/drivers/media/video/tda7432.c @@ -74,7 +74,6 @@ static unsigned short normal_i2c[] = { I2C_TDA7432 >> 1, I2C_CLIENT_END, }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; /* Structure of address and subaddresses for the tda7432 */ diff --git a/trunk/drivers/media/video/tda9840.c b/trunk/drivers/media/video/tda9840.c index b5177c6f54f6..c29bdfc3244e 100644 --- a/trunk/drivers/media/video/tda9840.c +++ b/trunk/drivers/media/video/tda9840.c @@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); /* addresses to scan, found only at 0x42 (7-Bit) */ static unsigned short normal_i2c[] = { I2C_TDA9840, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/media/video/tda9875.c b/trunk/drivers/media/video/tda9875.c index 4f1114c033a1..97b113e070f3 100644 --- a/trunk/drivers/media/video/tda9875.c +++ b/trunk/drivers/media/video/tda9875.c @@ -44,7 +44,6 @@ static unsigned short normal_i2c[] = { I2C_TDA9875 >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* This is a superset of the TDA9875 */ diff --git a/trunk/drivers/media/video/tda9887.c b/trunk/drivers/media/video/tda9887.c index debef1910c37..7e6e6dd966a2 100644 --- a/trunk/drivers/media/video/tda9887.c +++ b/trunk/drivers/media/video/tda9887.c @@ -33,7 +33,6 @@ static unsigned short normal_i2c[] = { 0x96 >>1, I2C_CLIENT_END, }; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* insmod options */ diff --git a/trunk/drivers/media/video/tea6415c.c b/trunk/drivers/media/video/tea6415c.c index 3ec39550bf46..b44db8a7b94d 100644 --- a/trunk/drivers/media/video/tea6415c.c +++ b/trunk/drivers/media/video/tea6415c.c @@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/media/video/tea6420.c b/trunk/drivers/media/video/tea6420.c index bd10710fd909..48d4db7d507b 100644 --- a/trunk/drivers/media/video/tea6420.c +++ b/trunk/drivers/media/video/tea6420.c @@ -40,7 +40,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/media/video/tuner-3036.c b/trunk/drivers/media/video/tuner-3036.c index 6b20aa902a8f..bedb15e2f233 100644 --- a/trunk/drivers/media/video/tuner-3036.c +++ b/trunk/drivers/media/video/tuner-3036.c @@ -34,19 +34,16 @@ static int this_adap; static struct i2c_client client_template; /* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {0x60, 0x61, I2C_CLIENT_END}; +static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force + .normal_i2c = normal_i2c, + .probe = probe, + .ignore = ignore, + .force = force, }; /* ---------------------------------------------------------------------- */ diff --git a/trunk/drivers/media/video/tuner-core.c b/trunk/drivers/media/video/tuner-core.c index 6212388edb75..81882ddab859 100644 --- a/trunk/drivers/media/video/tuner-core.c +++ b/trunk/drivers/media/video/tuner-core.c @@ -28,10 +28,8 @@ /* standard i2c insmod options */ static unsigned short normal_i2c[] = { 0x4b, /* tda8290 */ - I2C_CLIENT_END -}; -static unsigned short normal_i2c_range[] = { - 0x60, 0x6f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -225,9 +223,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) static int tuner_probe(struct i2c_adapter *adap) { if (0 != addr) { - normal_i2c[0] = addr; - normal_i2c_range[0] = addr; - normal_i2c_range[1] = addr; + normal_i2c[0] = addr; + normal_i2c[1] = I2C_CLIENT_END; } this_adap = 0; diff --git a/trunk/drivers/media/video/tvaudio.c b/trunk/drivers/media/video/tvaudio.c index 80dc34f18c2c..41b635e0d3c6 100644 --- a/trunk/drivers/media/video/tvaudio.c +++ b/trunk/drivers/media/video/tvaudio.c @@ -148,7 +148,6 @@ static unsigned short normal_i2c[] = { I2C_TDA9874 >> 1, I2C_PIC16C54 >> 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; static struct i2c_driver driver; diff --git a/trunk/drivers/media/video/tveeprom.c b/trunk/drivers/media/video/tveeprom.c index e1443a0937e3..3d216973798c 100644 --- a/trunk/drivers/media/video/tveeprom.c +++ b/trunk/drivers/media/video/tveeprom.c @@ -482,7 +482,6 @@ static unsigned short normal_i2c[] = { 0xa0 >> 1, I2C_CLIENT_END, }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; struct i2c_driver i2c_driver_tveeprom; diff --git a/trunk/drivers/media/video/vpx3220.c b/trunk/drivers/media/video/vpx3220.c index 0fd6c9a70917..b97036910fa9 100644 --- a/trunk/drivers/media/video/vpx3220.c +++ b/trunk/drivers/media/video/vpx3220.c @@ -569,21 +569,15 @@ static unsigned short normal_i2c[] = { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .probe = probe, - .probe_range = probe_range, .ignore = ignore, - .ignore_range = ignore_range, .force = force }; diff --git a/trunk/drivers/video/matrox/matroxfb_maven.c b/trunk/drivers/video/matrox/matroxfb_maven.c index e529841cd83d..67f85344f0cc 100644 --- a/trunk/drivers/video/matrox/matroxfb_maven.c +++ b/trunk/drivers/video/matrox/matroxfb_maven.c @@ -1230,7 +1230,6 @@ static int maven_shutdown_client(struct i2c_client* clnt) { } static unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { MAVEN_I2CID, MAVEN_I2CID, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; static struct i2c_driver maven_driver; diff --git a/trunk/drivers/w1/Kconfig b/trunk/drivers/w1/Kconfig index 4f120796273e..2ab65c902fe5 100644 --- a/trunk/drivers/w1/Kconfig +++ b/trunk/drivers/w1/Kconfig @@ -3,9 +3,9 @@ menu "Dallas's 1-wire bus" config W1 tristate "Dallas's 1-wire support" ---help--- - Dallas's 1-wire bus is usefull to connect slow 1-pin devices + Dallas's 1-wire bus is usefull to connect slow 1-pin devices such as iButtons and thermal sensors. - + If you want W1 support, you should say Y here. This W1 support can also be built as a module. If so, the module @@ -17,8 +17,8 @@ config W1_MATROX help Say Y here if you want to communicate with your 1-wire devices using Matrox's G400 GPIO pins. - - This support is also available as a module. If so, the module + + This support is also available as a module. If so, the module will be called matrox_w1.ko. config W1_DS9490 @@ -27,17 +27,17 @@ config W1_DS9490 help Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge. - This support is also available as a module. If so, the module + This support is also available as a module. If so, the module will be called ds9490r.ko. -config W1_DS9490R_BRIDGE +config W1_DS9490_BRIDGE tristate "DS9490R USB <-> W1 transport layer for 1-wire" depends on W1_DS9490 help Say Y here if you want to communicate with your 1-wire devices using DS9490R USB bridge. - This support is also available as a module. If so, the module + This support is also available as a module. If so, the module will be called ds_w1_bridge.ko. config W1_THERM @@ -51,7 +51,7 @@ config W1_SMEM tristate "Simple 64bit memory family implementation" depends on W1 help - Say Y here if you want to connect 1-wire + Say Y here if you want to connect 1-wire simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire. endmenu diff --git a/trunk/drivers/w1/ds_w1_bridge.c b/trunk/drivers/w1/ds_w1_bridge.c index 7bddd8ac7d7f..0baaeb5fd630 100644 --- a/trunk/drivers/w1/ds_w1_bridge.c +++ b/trunk/drivers/w1/ds_w1_bridge.c @@ -83,11 +83,11 @@ static u8 ds9490r_read_byte(unsigned long data) return byte; } -static void ds9490r_write_block(unsigned long data, const u8 *buf, int len) +static void ds9490r_write_block(unsigned long data, u8 *buf, int len) { struct ds_device *dev = (struct ds_device *)data; - ds_write_block(dev, (u8 *)buf, len); + ds_write_block(dev, buf, len); } static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len) diff --git a/trunk/drivers/w1/matrox_w1.c b/trunk/drivers/w1/matrox_w1.c index 0b03f8f93f63..e565416458ea 100644 --- a/trunk/drivers/w1/matrox_w1.c +++ b/trunk/drivers/w1/matrox_w1.c @@ -1,8 +1,8 @@ /* - * matrox_w1.c + * matrox_w1.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -59,7 +59,7 @@ static struct pci_driver matrox_w1_pci_driver = { .remove = __devexit_p(matrox_w1_remove), }; -/* +/* * Matrox G400 DDC registers. */ @@ -177,8 +177,8 @@ static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_devi dev->bus_master = (struct w1_bus_master *)(dev + 1); - /* - * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c + /* + * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c */ dev->phys_addr = pci_resource_start(pdev, 1); diff --git a/trunk/drivers/w1/w1.c b/trunk/drivers/w1/w1.c index b460927ec32a..24a192e3b8b4 100644 --- a/trunk/drivers/w1/w1.c +++ b/trunk/drivers/w1/w1.c @@ -1,8 +1,8 @@ /* - * w1.c + * w1.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -59,19 +59,6 @@ static pid_t control_thread; static int control_needs_exit; static DECLARE_COMPLETION(w1_control_complete); -/* stuff for the default family */ -static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - return(sprintf(buf, "%s\n", sl->name)); -} -static struct w1_family_ops w1_default_fops = { - .rname = &w1_famdefault_read_name, -}; -static struct w1_family w1_default_family = { - .fops = &w1_default_fops, -}; - static int w1_master_match(struct device *dev, struct device_driver *drv) { return 1; @@ -112,20 +99,6 @@ static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off, return sprintf(buf, "No family registered.\n"); } -static struct device_attribute w1_slave_attribute = - __ATTR(name, S_IRUGO, w1_default_read_name, NULL); - -static struct bin_attribute w1_slave_bin_attribute = { - .attr = { - .name = "w1_slave", - .mode = S_IRUGO, - .owner = THIS_MODULE, - }, - .size = W1_SLAVE_DATA_SIZE, - .read = &w1_default_read_bin, -}; - - static struct bus_type w1_bus_type = { .name = "w1", .match = w1_master_match, @@ -146,49 +119,34 @@ struct device w1_device = { .release = &w1_master_release }; -static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w1_master *md = container_of(dev, struct w1_master, dev); - ssize_t count; - - if (down_interruptible (&md->mutex)) - return -EBUSY; - - count = sprintf(buf, "%s\n", md->name); - - up(&md->mutex); - - return count; -} - -static ssize_t w1_master_attribute_store_search(struct device * dev, - struct device_attribute *attr, - const char * buf, size_t count) -{ - struct w1_master *md = container_of(dev, struct w1_master, dev); - - if (down_interruptible (&md->mutex)) - return -EBUSY; - - md->search_count = simple_strtol(buf, NULL, 0); - - up(&md->mutex); +static struct device_attribute w1_slave_attribute = { + .attr = { + .name = "name", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_default_read_name, +}; - return count; -} +static struct device_attribute w1_slave_attribute_val = { + .attr = { + .name = "value", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_default_read_name, +}; -static ssize_t w1_master_attribute_show_search(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_master *md = container_of(dev, struct w1_master, dev); + struct w1_master *md = container_of (dev, struct w1_master, dev); ssize_t count; - + if (down_interruptible (&md->mutex)) return -EBUSY; - count = sprintf(buf, "%d\n", md->search_count); - + count = sprintf(buf, "%s\n", md->name); + up(&md->mutex); return count; @@ -198,12 +156,12 @@ static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct devic { struct w1_master *md = container_of(dev, struct w1_master, dev); ssize_t count; - + if (down_interruptible(&md->mutex)) return -EBUSY; count = sprintf(buf, "0x%p\n", md->bus_master); - + up(&md->mutex); return count; } @@ -219,12 +177,12 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru { struct w1_master *md = container_of(dev, struct w1_master, dev); ssize_t count; - + if (down_interruptible(&md->mutex)) return -EBUSY; count = sprintf(buf, "%d\n", md->max_slave_count); - + up(&md->mutex); return count; } @@ -233,12 +191,12 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi { struct w1_master *md = container_of(dev, struct w1_master, dev); ssize_t count; - + if (down_interruptible(&md->mutex)) return -EBUSY; count = sprintf(buf, "%lu\n", md->attempts); - + up(&md->mutex); return count; } @@ -247,17 +205,18 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d { struct w1_master *md = container_of(dev, struct w1_master, dev); ssize_t count; - + if (down_interruptible(&md->mutex)) return -EBUSY; count = sprintf(buf, "%d\n", md->slave_count); - + up(&md->mutex); return count; } static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf) + { struct w1_master *md = container_of(dev, struct w1_master, dev); int c = PAGE_SIZE; @@ -274,7 +233,7 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device list_for_each_safe(ent, n, &md->slist) { sl = list_entry(ent, struct w1_slave, w1_slave_entry); - c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name); + c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name); } } @@ -283,51 +242,72 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device return PAGE_SIZE - c; } -#define W1_MASTER_ATTR_RO(_name, _mode) \ - struct device_attribute w1_master_attribute_##_name = \ - __ATTR(w1_master_##_name, _mode, \ - w1_master_attribute_show_##_name, NULL) - -#define W1_MASTER_ATTR_RW(_name, _mode) \ - struct device_attribute w1_master_attribute_##_name = \ - __ATTR(w1_master_##_name, _mode, \ - w1_master_attribute_show_##_name, \ - w1_master_attribute_store_##_name) - -static W1_MASTER_ATTR_RO(name, S_IRUGO); -static W1_MASTER_ATTR_RO(slaves, S_IRUGO); -static W1_MASTER_ATTR_RO(slave_count, S_IRUGO); -static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO); -static W1_MASTER_ATTR_RO(attempts, S_IRUGO); -static W1_MASTER_ATTR_RO(timeout, S_IRUGO); -static W1_MASTER_ATTR_RO(pointer, S_IRUGO); -static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); - -static struct attribute *w1_master_default_attrs[] = { - &w1_master_attribute_name.attr, - &w1_master_attribute_slaves.attr, - &w1_master_attribute_slave_count.attr, - &w1_master_attribute_max_slave_count.attr, - &w1_master_attribute_attempts.attr, - &w1_master_attribute_timeout.attr, - &w1_master_attribute_pointer.attr, - &w1_master_attribute_search.attr, - NULL +static struct device_attribute w1_master_attribute_slaves = { + .attr = { + .name = "w1_master_slaves", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .show = &w1_master_attribute_show_slaves, }; - -static struct attribute_group w1_master_defattr_group = { - .attrs = w1_master_default_attrs, +static struct device_attribute w1_master_attribute_slave_count = { + .attr = { + .name = "w1_master_slave_count", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_master_attribute_show_slave_count, +}; +static struct device_attribute w1_master_attribute_attempts = { + .attr = { + .name = "w1_master_attempts", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_master_attribute_show_attempts, +}; +static struct device_attribute w1_master_attribute_max_slave_count = { + .attr = { + .name = "w1_master_max_slave_count", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_master_attribute_show_max_slave_count, +}; +static struct device_attribute w1_master_attribute_timeout = { + .attr = { + .name = "w1_master_timeout", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_master_attribute_show_timeout, +}; +static struct device_attribute w1_master_attribute_pointer = { + .attr = { + .name = "w1_master_pointer", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_master_attribute_show_pointer, +}; +static struct device_attribute w1_master_attribute_name = { + .attr = { + .name = "w1_master_name", + .mode = S_IRUGO, + .owner = THIS_MODULE + }, + .show = &w1_master_attribute_show_name, }; -int w1_create_master_attributes(struct w1_master *master) -{ - return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); -} - -void w1_destroy_master_attributes(struct w1_master *master) -{ - sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); -} +static struct bin_attribute w1_slave_bin_attribute = { + .attr = { + .name = "w1_slave", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = W1_SLAVE_DATA_SIZE, + .read = &w1_default_read_bin, +}; static int __w1_attach_slave_device(struct w1_slave *sl) { @@ -339,13 +319,13 @@ static int __w1_attach_slave_device(struct w1_slave *sl) sl->dev.release = &w1_slave_release; snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id), - "%02x-%012llx", - (unsigned int) sl->reg_num.family, - (unsigned long long) sl->reg_num.id); - snprintf(&sl->name[0], sizeof(sl->name), - "%02x-%012llx", - (unsigned int) sl->reg_num.family, - (unsigned long long) sl->reg_num.id); + "%02x-%012llx", + (unsigned int) sl->reg_num.family, + (unsigned long long) sl->reg_num.id); + snprintf (&sl->name[0], sizeof(sl->name), + "%02x-%012llx", + (unsigned int) sl->reg_num.family, + (unsigned long long) sl->reg_num.id); dev_dbg(&sl->dev, "%s: registering %s.\n", __func__, &sl->dev.bus_id[0]); @@ -353,36 +333,48 @@ static int __w1_attach_slave_device(struct w1_slave *sl) err = device_register(&sl->dev); if (err < 0) { dev_err(&sl->dev, - "Device registration [%s] failed. err=%d\n", - sl->dev.bus_id, err); + "Device registration [%s] failed. err=%d\n", + sl->dev.bus_id, err); return err; } memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin)); memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name)); - + memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val)); + sl->attr_bin.read = sl->family->fops->rbin; sl->attr_name.show = sl->family->fops->rname; + sl->attr_val.show = sl->family->fops->rval; + sl->attr_val.attr.name = sl->family->fops->rvalname; err = device_create_file(&sl->dev, &sl->attr_name); if (err < 0) { dev_err(&sl->dev, - "sysfs file creation for [%s] failed. err=%d\n", - sl->dev.bus_id, err); + "sysfs file creation for [%s] failed. err=%d\n", + sl->dev.bus_id, err); device_unregister(&sl->dev); return err; } - if ( sl->attr_bin.read ) { - err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin); - if (err < 0) { - dev_err(&sl->dev, - "sysfs file creation for [%s] failed. err=%d\n", - sl->dev.bus_id, err); - device_remove_file(&sl->dev, &sl->attr_name); - device_unregister(&sl->dev); - return err; - } + err = device_create_file(&sl->dev, &sl->attr_val); + if (err < 0) { + dev_err(&sl->dev, + "sysfs file creation for [%s] failed. err=%d\n", + sl->dev.bus_id, err); + device_remove_file(&sl->dev, &sl->attr_name); + device_unregister(&sl->dev); + return err; + } + + err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin); + if (err < 0) { + dev_err(&sl->dev, + "sysfs file creation for [%s] failed. err=%d\n", + sl->dev.bus_id, err); + device_remove_file(&sl->dev, &sl->attr_name); + device_remove_file(&sl->dev, &sl->attr_val); + device_unregister(&sl->dev); + return err; } list_add_tail(&sl->w1_slave_entry, &sl->master->slist); @@ -418,10 +410,12 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) spin_lock(&w1_flock); f = w1_family_registered(rn->family); if (!f) { - f= &w1_default_family; + spin_unlock(&w1_flock); dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n", rn->family, rn->family, (unsigned long long)rn->id, rn->crc); + kfree(sl); + return -ENODEV; } __w1_family_get(f); spin_unlock(&w1_flock); @@ -451,7 +445,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) static void w1_slave_detach(struct w1_slave *sl) { struct w1_netlink_msg msg; - + dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name); while (atomic_read(&sl->refcnt)) { @@ -462,15 +456,12 @@ static void w1_slave_detach(struct w1_slave *sl) flush_signals(current); } - if ( sl->attr_bin.read ) { - sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin); - } + sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin); device_remove_file(&sl->dev, &sl->attr_name); + device_remove_file(&sl->dev, &sl->attr_val); device_unregister(&sl->dev); w1_family_put(sl->family); - sl->master->slave_count--; - memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); msg.type = W1_SLAVE_REMOVE; w1_netlink_send(sl->master, &msg); @@ -480,8 +471,8 @@ static struct w1_master *w1_search_master(unsigned long data) { struct w1_master *dev; int found = 0; - - spin_lock_bh(&w1_mlock); + + spin_lock_irq(&w1_mlock); list_for_each_entry(dev, &w1_masters, w1_master_entry) { if (dev->bus_master->data == data) { found = 1; @@ -489,26 +480,12 @@ static struct w1_master *w1_search_master(unsigned long data) break; } } - spin_unlock_bh(&w1_mlock); + spin_unlock_irq(&w1_mlock); return (found)?dev:NULL; } -void w1_reconnect_slaves(struct w1_family *f) -{ - struct w1_master *dev; - - spin_lock_bh(&w1_mlock); - list_for_each_entry(dev, &w1_masters, w1_master_entry) { - dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", - dev->name, f->fid); - set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); - } - spin_unlock_bh(&w1_mlock); -} - - -static void w1_slave_found(unsigned long data, u64 rn) +void w1_slave_found(unsigned long data, u64 rn) { int slave_count; struct w1_slave *sl; @@ -523,7 +500,7 @@ static void w1_slave_found(unsigned long data, u64 rn) data); return; } - + tmp = (struct w1_reg_num *) &rn; slave_count = 0; @@ -536,7 +513,8 @@ static void w1_slave_found(unsigned long data, u64 rn) sl->reg_num.crc == tmp->crc) { set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); break; - } else if (sl->reg_num.family == tmp->family) { + } + else if (sl->reg_num.family == tmp->family) { family_found = 1; break; } @@ -550,43 +528,30 @@ static void w1_slave_found(unsigned long data, u64 rn) rn && ((le64_to_cpu(rn) >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) { w1_attach_slave_device(dev, tmp); } - + atomic_dec(&dev->refcnt); } -/** - * Performs a ROM Search & registers any devices found. - * The 1-wire search is a simple binary tree search. - * For each bit of the address, we read two bits and write one bit. - * The bit written will put to sleep all devies that don't match that bit. - * When the two reads differ, the direction choice is obvious. - * When both bits are 0, we must choose a path to take. - * When we can scan all 64 bits without having to choose a path, we are done. - * - * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com - * - * @dev The master device to search - * @cb Function to call when a device is found - */ -void w1_search(struct w1_master *dev, w1_slave_found_callback cb) +void w1_search(struct w1_master *dev) { - u64 last_rn, rn, tmp64; - int i, slave_count = 0; - int last_zero, last_device; - int search_bit, desc_bit; - u8 triplet_ret = 0; + u64 last, rn, tmp; + int i, count = 0; + int last_family_desc, last_zero, last_device; + int search_bit, id_bit, comp_bit, desc_bit; - search_bit = 0; - rn = last_rn = 0; - last_device = 0; - last_zero = -1; + search_bit = id_bit = comp_bit = 0; + rn = tmp = last = 0; + last_device = last_zero = last_family_desc = 0; desc_bit = 64; - while ( !last_device && (slave_count++ < dev->max_slave_count) ) { - last_rn = rn; + while (!(id_bit && comp_bit) && !last_device + && count++ < dev->max_slave_count) { + last = rn; rn = 0; + last_family_desc = 0; + /* * Reset bus and all 1-wire device state machines * so they can respond to our requests. @@ -598,46 +563,94 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb) break; } - /* Start the search */ +#if 1 w1_write_8(dev, W1_SEARCH); for (i = 0; i < 64; ++i) { - /* Determine the direction/search bit */ - if (i == desc_bit) - search_bit = 1; /* took the 0 path last time, so take the 1 path */ - else if (i > desc_bit) - search_bit = 0; /* take the 0 path on the next branch */ - else - search_bit = ((last_rn >> i) & 0x1); - - /** Read two bits and write one bit */ - triplet_ret = w1_triplet(dev, search_bit); + /* + * Read 2 bits from bus. + * All who don't sleep must send ID bit and COMPLEMENT ID bit. + * They actually are ANDed between all senders. + */ + id_bit = w1_touch_bit(dev, 1); + comp_bit = w1_touch_bit(dev, 1); - /* quit if no device responded */ - if ( (triplet_ret & 0x03) == 0x03 ) + if (id_bit && comp_bit) break; - /* If both directions were valid, and we took the 0 path... */ - if (triplet_ret == 0) - last_zero = i; + if (id_bit == 0 && comp_bit == 0) { + if (i == desc_bit) + search_bit = 1; + else if (i > desc_bit) + search_bit = 0; + else + search_bit = ((last >> i) & 0x1); + + if (search_bit == 0) { + last_zero = i; + if (last_zero < 9) + last_family_desc = last_zero; + } + + } + else + search_bit = id_bit; - /* extract the direction taken & update the device number */ - tmp64 = (triplet_ret >> 2); - rn |= (tmp64 << i); - } + tmp = search_bit; + rn |= (tmp << i); + + /* + * Write 1 bit to bus + * and make all who don't have "search_bit" in "i"'th position + * in it's registration number sleep. + */ + if (dev->bus_master->touch_bit) + w1_touch_bit(dev, search_bit); + else + w1_write_bit(dev, search_bit); - if ( (triplet_ret & 0x03) != 0x03 ) { - if ( (desc_bit == last_zero) || (last_zero < 0)) - last_device = 1; - desc_bit = last_zero; - cb(dev->bus_master->data, rn); } +#endif + + if (desc_bit == last_zero) + last_device = 1; + + desc_bit = last_zero; + + w1_slave_found(dev->bus_master->data, rn); } } -static int w1_control(void *data) +int w1_create_master_attributes(struct w1_master *dev) +{ + if ( device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 || + device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 || + device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 || + device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 || + device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0|| + device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0|| + device_create_file(&dev->dev, &w1_master_attribute_name) < 0) + return -EINVAL; + + return 0; +} + +void w1_destroy_master_attributes(struct w1_master *dev) { - struct w1_slave *sl, *sln; - struct w1_master *dev, *n; + device_remove_file(&dev->dev, &w1_master_attribute_slaves); + device_remove_file(&dev->dev, &w1_master_attribute_slave_count); + device_remove_file(&dev->dev, &w1_master_attribute_attempts); + device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count); + device_remove_file(&dev->dev, &w1_master_attribute_timeout); + device_remove_file(&dev->dev, &w1_master_attribute_pointer); + device_remove_file(&dev->dev, &w1_master_attribute_name); +} + + +int w1_control(void *data) +{ + struct w1_slave *sl; + struct w1_master *dev; + struct list_head *ent, *ment, *n, *mn; int err, have_to_wait = 0; daemonize("w1_control"); @@ -652,8 +665,10 @@ static int w1_control(void *data) if (signal_pending(current)) flush_signals(current); - list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) { - if (!control_needs_exit && !dev->flags) + list_for_each_safe(ment, mn, &w1_masters) { + dev = list_entry(ment, struct w1_master, w1_master_entry); + + if (!control_needs_exit && !dev->need_exit) continue; /* * Little race: we can create thread but not set the flag. @@ -664,8 +679,12 @@ static int w1_control(void *data) continue; } + spin_lock(&w1_mlock); + list_del(&dev->w1_master_entry); + spin_unlock(&w1_mlock); + if (control_needs_exit) { - set_bit(W1_MASTER_NEED_EXIT, &dev->flags); + dev->need_exit = 1; err = kill_proc(dev->kpid, SIGTERM, 1); if (err) @@ -674,42 +693,24 @@ static int w1_control(void *data) dev->kpid); } - if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { - wait_for_completion(&dev->dev_exited); - spin_lock_bh(&w1_mlock); - list_del(&dev->w1_master_entry); - spin_unlock_bh(&w1_mlock); + wait_for_completion(&dev->dev_exited); + + list_for_each_safe(ent, n, &dev->slist) { + sl = list_entry(ent, struct w1_slave, w1_slave_entry); - list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { + if (!sl) + dev_warn(&dev->dev, + "%s: slave entry is NULL.\n", + __func__); + else { list_del(&sl->w1_slave_entry); w1_slave_detach(sl); kfree(sl); } - w1_destroy_master_attributes(dev); - atomic_dec(&dev->refcnt); - continue; - } - - if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { - dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); - down(&dev->mutex); - list_for_each_entry(sl, &dev->slist, w1_slave_entry) { - if (sl->family->fid == W1_FAMILY_DEFAULT) { - struct w1_reg_num rn; - list_del(&sl->w1_slave_entry); - w1_slave_detach(sl); - - memcpy(&rn, &sl->reg_num, sizeof(rn)); - - kfree(sl); - - w1_attach_slave_device(dev, &rn); - } - } - clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); - up(&dev->mutex); } + w1_destroy_master_attributes(dev); + atomic_dec(&dev->refcnt); } } @@ -719,50 +720,51 @@ static int w1_control(void *data) int w1_process(void *data) { struct w1_master *dev = (struct w1_master *) data; - struct w1_slave *sl, *sln; + struct list_head *ent, *n; + struct w1_slave *sl; daemonize("%s", dev->name); allow_signal(SIGTERM); - while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { + while (!dev->need_exit) { try_to_freeze(PF_FREEZE); msleep_interruptible(w1_timeout * 1000); if (signal_pending(current)) flush_signals(current); - if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) + if (dev->need_exit) break; if (!dev->initialized) continue; - if (dev->search_count == 0) - continue; - if (down_interruptible(&dev->mutex)) continue; - list_for_each_entry(sl, &dev->slist, w1_slave_entry) - clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); + list_for_each_safe(ent, n, &dev->slist) { + sl = list_entry(ent, struct w1_slave, w1_slave_entry); + if (sl) + clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); + } + w1_search_devices(dev, w1_slave_found); - list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { - if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { + list_for_each_safe(ent, n, &dev->slist) { + sl = list_entry(ent, struct w1_slave, w1_slave_entry); + + if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { list_del (&sl->w1_slave_entry); w1_slave_detach (sl); kfree (sl); dev->slave_count--; - } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) + } + else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) sl->ttl = dev->slave_ttl; } - - if (dev->search_count > 0) - dev->search_count--; - up(&dev->mutex); } @@ -772,7 +774,7 @@ int w1_process(void *data) return 0; } -static int w1_init(void) +int w1_init(void) { int retval; @@ -812,14 +814,18 @@ static int w1_init(void) return retval; } -static void w1_fini(void) +void w1_fini(void) { struct w1_master *dev; + struct list_head *ent, *n; - list_for_each_entry(dev, &w1_masters, w1_master_entry) + list_for_each_safe(ent, n, &w1_masters) { + dev = list_entry(ent, struct w1_master, w1_master_entry); __w1_remove_master_device(dev); + } control_needs_exit = 1; + wait_for_completion(&w1_control_complete); driver_unregister(&w1_driver); diff --git a/trunk/drivers/w1/w1.h b/trunk/drivers/w1/w1.h index 4f0a986e33e3..abbddaf3f8e2 100644 --- a/trunk/drivers/w1/w1.h +++ b/trunk/drivers/w1/w1.h @@ -1,8 +1,8 @@ /* - * w1.h + * w1.h * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -74,86 +74,36 @@ struct w1_slave int ttl; struct w1_master *master; - struct w1_family *family; - struct device dev; - struct completion dev_released; + struct w1_family *family; + struct device dev; + struct completion dev_released; - struct bin_attribute attr_bin; - struct device_attribute attr_name; + struct bin_attribute attr_bin; + struct device_attribute attr_name, attr_val; }; typedef void (* w1_slave_found_callback)(unsigned long, u64); - -/** - * Note: read_bit and write_bit are very low level functions and should only - * be used with hardware that doesn't really support 1-wire operations, - * like a parallel/serial port. - * Either define read_bit and write_bit OR define, at minimum, touch_bit and - * reset_bus. - */ struct w1_bus_master { - /** the first parameter in all the functions below */ - unsigned long data; - - /** - * Sample the line level - * @return the level read (0 or 1) - */ - u8 (*read_bit)(unsigned long); - - /** Sets the line level */ - void (*write_bit)(unsigned long, u8); - - /** - * touch_bit is the lowest-level function for devices that really - * support the 1-wire protocol. - * touch_bit(0) = write-0 cycle - * touch_bit(1) = write-1 / read cycle - * @return the bit read (0 or 1) - */ - u8 (*touch_bit)(unsigned long, u8); - - /** - * Reads a bytes. Same as 8 touch_bit(1) calls. - * @return the byte read - */ - u8 (*read_byte)(unsigned long); - - /** - * Writes a byte. Same as 8 touch_bit(x) calls. - */ - void (*write_byte)(unsigned long, u8); - - /** - * Same as a series of read_byte() calls - * @return the number of bytes read - */ - u8 (*read_block)(unsigned long, u8 *, int); - - /** Same as a series of write_byte() calls */ - void (*write_block)(unsigned long, const u8 *, int); - - /** - * Combines two reads and a smart write for ROM searches - * @return bit0=Id bit1=comp_id bit2=dir_taken - */ - u8 (*triplet)(unsigned long, u8); - - /** - * long write-0 with a read for the presence pulse detection - * @return -1=Error, 0=Device present, 1=No device present - */ - u8 (*reset_bus)(unsigned long); - - /** Really nice hardware can handles the ROM searches */ - void (*search)(unsigned long, w1_slave_found_callback); + unsigned long data; + + u8 (*read_bit)(unsigned long); + void (*write_bit)(unsigned long, u8); + + u8 (*read_byte)(unsigned long); + void (*write_byte)(unsigned long, u8); + + u8 (*read_block)(unsigned long, u8 *, int); + void (*write_block)(unsigned long, u8 *, int); + + u8 (*touch_bit)(unsigned long, u8); + + u8 (*reset_bus)(unsigned long); + + void (*search)(unsigned long, w1_slave_found_callback); }; -#define W1_MASTER_NEED_EXIT 0 -#define W1_MASTER_NEED_RECONNECT 1 - struct w1_master { struct list_head w1_master_entry; @@ -165,31 +115,30 @@ struct w1_master int slave_ttl; int initialized; u32 id; - int search_count; atomic_t refcnt; void *priv; int priv_size; - long flags; - + int need_exit; pid_t kpid; - struct semaphore mutex; + struct semaphore mutex; struct device_driver *driver; - struct device dev; - struct completion dev_released; - struct completion dev_exited; + struct device dev; + struct completion dev_released; + struct completion dev_exited; struct w1_bus_master *bus_master; u32 seq, groups; - struct sock *nls; + struct sock *nls; }; int w1_create_master_attributes(struct w1_master *); -void w1_search(struct w1_master *dev, w1_slave_found_callback cb); +void w1_destroy_master_attributes(struct w1_master *); +void w1_search(struct w1_master *dev); #endif /* __KERNEL__ */ diff --git a/trunk/drivers/w1/w1_family.c b/trunk/drivers/w1/w1_family.c index 02eee57d3c0c..d1d56eca1061 100644 --- a/trunk/drivers/w1/w1_family.c +++ b/trunk/drivers/w1/w1_family.c @@ -1,8 +1,8 @@ /* - * w1_family.c + * w1_family.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -27,11 +27,10 @@ DEFINE_SPINLOCK(w1_flock); static LIST_HEAD(w1_families); -extern void w1_reconnect_slaves(struct w1_family *f); static int w1_check_family(struct w1_family *f) { - if (!f->fops->rname || !f->fops->rbin) + if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname) return -EINVAL; return 0; @@ -61,9 +60,8 @@ int w1_register_family(struct w1_family *newf) newf->need_exit = 0; list_add_tail(&newf->family_entry, &w1_families); } - spin_unlock(&w1_flock); - w1_reconnect_slaves(newf); + spin_unlock(&w1_flock); return ret; } diff --git a/trunk/drivers/w1/w1_family.h b/trunk/drivers/w1/w1_family.h index b26da01bbc38..07fa49412a90 100644 --- a/trunk/drivers/w1/w1_family.h +++ b/trunk/drivers/w1/w1_family.h @@ -1,8 +1,8 @@ /* - * w1_family.h + * w1_family.h * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -27,11 +27,8 @@ #include #define W1_FAMILY_DEFAULT 0 -#define W1_FAMILY_SMEM_01 0x01 -#define W1_FAMILY_SMEM_81 0x81 -#define W1_THERM_DS18S20 0x10 -#define W1_THERM_DS1822 0x22 -#define W1_THERM_DS18B20 0x28 +#define W1_FAMILY_THERM 0x10 +#define W1_FAMILY_SMEM 0x01 #define MAXNAMELEN 32 @@ -39,15 +36,18 @@ struct w1_family_ops { ssize_t (* rname)(struct device *, struct device_attribute *, char *); ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t); + + ssize_t (* rval)(struct device *, struct device_attribute *, char *); + unsigned char rvalname[MAXNAMELEN]; }; struct w1_family { struct list_head family_entry; u8 fid; - + struct w1_family_ops *fops; - + atomic_t refcnt; u8 need_exit; }; diff --git a/trunk/drivers/w1/w1_int.c b/trunk/drivers/w1/w1_int.c index 35e85d961702..5f0bafbbd575 100644 --- a/trunk/drivers/w1/w1_int.c +++ b/trunk/drivers/w1/w1_int.c @@ -1,8 +1,8 @@ /* - * w1_int.c + * w1_int.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -39,9 +39,8 @@ extern spinlock_t w1_mlock; extern int w1_process(void *); -static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, - struct device_driver *driver, - struct device *device) +struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, + struct device_driver *driver, struct device *device) { struct w1_master *dev; int err; @@ -61,15 +60,14 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, dev->bus_master = (struct w1_bus_master *)(dev + 1); - dev->owner = THIS_MODULE; - dev->max_slave_count = slave_count; - dev->slave_count = 0; - dev->attempts = 0; - dev->kpid = -1; - dev->initialized = 0; - dev->id = id; + dev->owner = THIS_MODULE; + dev->max_slave_count = slave_count; + dev->slave_count = 0; + dev->attempts = 0; + dev->kpid = -1; + dev->initialized = 0; + dev->id = id; dev->slave_ttl = slave_ttl; - dev->search_count = -1; /* continual scan */ atomic_set(&dev->refcnt, 2); @@ -107,7 +105,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, return dev; } -static void w1_free_dev(struct w1_master *dev) +void w1_free_dev(struct w1_master *dev) { device_unregister(&dev->dev); if (dev->nls && dev->nls->sk_socket) @@ -122,13 +120,6 @@ int w1_add_master_device(struct w1_bus_master *master) int retval = 0; struct w1_netlink_msg msg; - /* validate minimum functionality */ - if (!(master->touch_bit && master->reset_bus) && - !(master->write_bit && master->read_bit)) { - printk(KERN_ERR "w1_add_master_device: invalid function set\n"); - return(-EINVAL); - } - dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device); if (!dev) return -ENOMEM; @@ -162,7 +153,7 @@ int w1_add_master_device(struct w1_bus_master *master) return 0; err_out_kill_thread: - set_bit(W1_MASTER_NEED_EXIT, &dev->flags); + dev->need_exit = 1; if (kill_proc(dev->kpid, SIGTERM, 1)) dev_err(&dev->dev, "Failed to send signal to w1 kernel thread %d.\n", @@ -180,7 +171,7 @@ void __w1_remove_master_device(struct w1_master *dev) int err; struct w1_netlink_msg msg; - set_bit(W1_MASTER_NEED_EXIT, &dev->flags); + dev->need_exit = 1; err = kill_proc(dev->kpid, SIGTERM, 1); if (err) dev_err(&dev->dev, @@ -206,8 +197,10 @@ void __w1_remove_master_device(struct w1_master *dev) void w1_remove_master_device(struct w1_bus_master *bm) { struct w1_master *dev = NULL; + struct list_head *ent, *n; - list_for_each_entry(dev, &w1_masters, w1_master_entry) { + list_for_each_safe(ent, n, &w1_masters) { + dev = list_entry(ent, struct w1_master, w1_master_entry); if (!dev->initialized) continue; diff --git a/trunk/drivers/w1/w1_int.h b/trunk/drivers/w1/w1_int.h index 4274082d2262..fdb531e87faa 100644 --- a/trunk/drivers/w1/w1_int.h +++ b/trunk/drivers/w1/w1_int.h @@ -1,8 +1,8 @@ /* - * w1_int.h + * w1_int.h * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -27,6 +27,8 @@ #include "w1.h" +struct w1_master * w1_alloc_dev(u32, int, int, struct device_driver *, struct device *); +void w1_free_dev(struct w1_master *dev); int w1_add_master_device(struct w1_bus_master *); void w1_remove_master_device(struct w1_bus_master *); void __w1_remove_master_device(struct w1_master *); diff --git a/trunk/drivers/w1/w1_io.c b/trunk/drivers/w1/w1_io.c index 00f032220173..02796b5a39f6 100644 --- a/trunk/drivers/w1/w1_io.c +++ b/trunk/drivers/w1/w1_io.c @@ -1,8 +1,8 @@ /* - * w1_io.c + * w1_io.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -55,29 +55,15 @@ void w1_delay(unsigned long tm) udelay(tm * w1_delay_parm); } -static void w1_write_bit(struct w1_master *dev, int bit); -static u8 w1_read_bit(struct w1_master *dev); - -/** - * Generates a write-0 or write-1 cycle and samples the level. - */ u8 w1_touch_bit(struct w1_master *dev, int bit) { if (dev->bus_master->touch_bit) return dev->bus_master->touch_bit(dev->bus_master->data, bit); - else if (bit) + else return w1_read_bit(dev); - else { - w1_write_bit(dev, 0); - return(0); - } } -/** - * Generates a write-0 or write-1 cycle. - * Only call if dev->bus_master->touch_bit is NULL - */ -static void w1_write_bit(struct w1_master *dev, int bit) +void w1_write_bit(struct w1_master *dev, int bit) { if (bit) { dev->bus_master->write_bit(dev->bus_master->data, 0); @@ -92,12 +78,6 @@ static void w1_write_bit(struct w1_master *dev, int bit) } } -/** - * Writes 8 bits. - * - * @param dev the master device - * @param byte the byte to write - */ void w1_write_8(struct w1_master *dev, u8 byte) { int i; @@ -106,15 +86,10 @@ void w1_write_8(struct w1_master *dev, u8 byte) dev->bus_master->write_byte(dev->bus_master->data, byte); else for (i = 0; i < 8; ++i) - w1_touch_bit(dev, (byte >> i) & 0x1); + w1_write_bit(dev, (byte >> i) & 0x1); } - -/** - * Generates a write-1 cycle and samples the level. - * Only call if dev->bus_master->touch_bit is NULL - */ -static u8 w1_read_bit(struct w1_master *dev) +u8 w1_read_bit(struct w1_master *dev) { int result; @@ -129,53 +104,6 @@ static u8 w1_read_bit(struct w1_master *dev) return result & 0x1; } -/** - * Does a triplet - used for searching ROM addresses. - * Return bits: - * bit 0 = id_bit - * bit 1 = comp_bit - * bit 2 = dir_taken - * If both bits 0 & 1 are set, the search should be restarted. - * - * @param dev the master device - * @param bdir the bit to write if both id_bit and comp_bit are 0 - * @return bit fields - see above - */ -u8 w1_triplet(struct w1_master *dev, int bdir) -{ - if ( dev->bus_master->triplet ) - return(dev->bus_master->triplet(dev->bus_master->data, bdir)); - else { - u8 id_bit = w1_touch_bit(dev, 1); - u8 comp_bit = w1_touch_bit(dev, 1); - u8 retval; - - if ( id_bit && comp_bit ) - return(0x03); /* error */ - - if ( !id_bit && !comp_bit ) { - /* Both bits are valid, take the direction given */ - retval = bdir ? 0x04 : 0; - } else { - /* Only one bit is valid, take that direction */ - bdir = id_bit; - retval = id_bit ? 0x05 : 0x02; - } - - if ( dev->bus_master->touch_bit ) - w1_touch_bit(dev, bdir); - else - w1_write_bit(dev, bdir); - return(retval); - } -} - -/** - * Reads 8 bits. - * - * @param dev the master device - * @return the byte read - */ u8 w1_read_8(struct w1_master * dev) { int i; @@ -185,20 +113,12 @@ u8 w1_read_8(struct w1_master * dev) res = dev->bus_master->read_byte(dev->bus_master->data); else for (i = 0; i < 8; ++i) - res |= (w1_touch_bit(dev,1) << i); + res |= (w1_read_bit(dev) << i); return res; } -/** - * Writes a series of bytes. - * - * @param dev the master device - * @param buf pointer to the data to write - * @param len the number of bytes to write - * @return the byte read - */ -void w1_write_block(struct w1_master *dev, const u8 *buf, int len) +void w1_write_block(struct w1_master *dev, u8 *buf, int len) { int i; @@ -209,14 +129,6 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len) w1_write_8(dev, buf[i]); } -/** - * Reads a series of bytes. - * - * @param dev the master device - * @param buf pointer to the buffer to fill - * @param len the number of bytes to read - * @return the number of bytes read - */ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len) { int i; @@ -233,15 +145,9 @@ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len) return ret; } -/** - * Issues a reset bus sequence. - * - * @param dev The bus master pointer - * @return 0=Device present, 1=No device present or error - */ int w1_reset_bus(struct w1_master *dev) { - int result; + int result = 0; if (dev->bus_master->reset_bus) result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; @@ -274,11 +180,12 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb) if (dev->bus_master->search) dev->bus_master->search(dev->bus_master->data, cb); else - w1_search(dev, cb); + w1_search(dev); } -EXPORT_SYMBOL(w1_touch_bit); +EXPORT_SYMBOL(w1_write_bit); EXPORT_SYMBOL(w1_write_8); +EXPORT_SYMBOL(w1_read_bit); EXPORT_SYMBOL(w1_read_8); EXPORT_SYMBOL(w1_reset_bus); EXPORT_SYMBOL(w1_calc_crc8); diff --git a/trunk/drivers/w1/w1_io.h b/trunk/drivers/w1/w1_io.h index af5829778aaa..6c573005a712 100644 --- a/trunk/drivers/w1/w1_io.h +++ b/trunk/drivers/w1/w1_io.h @@ -1,8 +1,8 @@ /* - * w1_io.h + * w1_io.h * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 @@ -26,12 +26,13 @@ void w1_delay(unsigned long); u8 w1_touch_bit(struct w1_master *, int); -u8 w1_triplet(struct w1_master *dev, int bdir); +void w1_write_bit(struct w1_master *, int); void w1_write_8(struct w1_master *, u8); +u8 w1_read_bit(struct w1_master *); u8 w1_read_8(struct w1_master *); int w1_reset_bus(struct w1_master *); u8 w1_calc_crc8(u8 *, int); -void w1_write_block(struct w1_master *, const u8 *, int); +void w1_write_block(struct w1_master *, u8 *, int); u8 w1_read_block(struct w1_master *, u8 *, int); void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb); diff --git a/trunk/drivers/w1/w1_log.h b/trunk/drivers/w1/w1_log.h index fe6bdf43380f..a6bf6f44dce2 100644 --- a/trunk/drivers/w1/w1_log.h +++ b/trunk/drivers/w1/w1_log.h @@ -1,8 +1,8 @@ /* - * w1_log.h + * w1_log.h * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * 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 diff --git a/trunk/drivers/w1/w1_netlink.h b/trunk/drivers/w1/w1_netlink.h index 8615756946df..ea1b530abad0 100644 --- a/trunk/drivers/w1/w1_netlink.h +++ b/trunk/drivers/w1/w1_netlink.h @@ -33,13 +33,13 @@ enum w1_netlink_message_types { W1_MASTER_REMOVE, }; -struct w1_netlink_msg +struct w1_netlink_msg { __u8 type; __u8 reserved[3]; union { - struct w1_reg_num id; + struct w1_reg_num id; __u64 w1_id; struct { diff --git a/trunk/drivers/w1/w1_smem.c b/trunk/drivers/w1/w1_smem.c index 70d2d469963c..674eb75a9bad 100644 --- a/trunk/drivers/w1/w1_smem.c +++ b/trunk/drivers/w1/w1_smem.c @@ -1,8 +1,8 @@ /* - * w1_smem.c + * w1_smem.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * This program is free software; you can redistribute it and/or modify * it under the smems of the GNU General Public License as published by @@ -37,11 +37,14 @@ MODULE_AUTHOR("Evgeniy Polyakov "); MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *); +static ssize_t w1_smem_read_val(struct device *, struct device_attribute *attr, char *); static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t); static struct w1_family_ops w1_smem_fops = { .rname = &w1_smem_read_name, .rbin = &w1_smem_read_bin, + .rval = &w1_smem_read_val, + .rvalname = "id", }; static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -51,10 +54,23 @@ static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *at return sprintf(buf, "%s\n", sl->name); } +static ssize_t w1_smem_read_val(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); + int i; + ssize_t count = 0; + + for (i = 0; i < 8; ++i) + count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]); + count += sprintf(buf + count, "\n"); + + return count; +} + static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj), - struct w1_slave, dev); + struct w1_slave, dev); int i; atomic_inc(&sl->refcnt); @@ -74,7 +90,7 @@ static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, siz for (i = 0; i < 8; ++i) count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]); count += sprintf(buf + count, "\n"); - + out: up(&sl->master->mutex); out_dec: @@ -83,37 +99,19 @@ static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, siz return count; } -static struct w1_family w1_smem_family_01 = { - .fid = W1_FAMILY_SMEM_01, - .fops = &w1_smem_fops, -}; - -static struct w1_family w1_smem_family_81 = { - .fid = W1_FAMILY_SMEM_81, +static struct w1_family w1_smem_family = { + .fid = W1_FAMILY_SMEM, .fops = &w1_smem_fops, }; static int __init w1_smem_init(void) { - int err; - - err = w1_register_family(&w1_smem_family_01); - if (err) - return err; - - err = w1_register_family(&w1_smem_family_81); - if (err) { - w1_unregister_family(&w1_smem_family_01); - return err; - } - - return 0; + return w1_register_family(&w1_smem_family); } static void __exit w1_smem_fini(void) { - w1_unregister_family(&w1_smem_family_01); - w1_unregister_family(&w1_smem_family_81); + w1_unregister_family(&w1_smem_family); } module_init(w1_smem_init); diff --git a/trunk/drivers/w1/w1_therm.c b/trunk/drivers/w1/w1_therm.c index 165526c9360a..70310f7a722e 100644 --- a/trunk/drivers/w1/w1_therm.c +++ b/trunk/drivers/w1/w1_therm.c @@ -1,8 +1,8 @@ /* - * w1_therm.c + * w1_therm.c * * Copyright (c) 2004 Evgeniy Polyakov - * + * * * This program is free software; you can redistribute it and/or modify * it under the therms of the GNU General Public License as published by @@ -38,56 +38,19 @@ MODULE_AUTHOR("Evgeniy Polyakov "); MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); static u8 bad_roms[][9] = { - {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, + {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, {} }; static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *); +static ssize_t w1_therm_read_temp(struct device *, struct device_attribute *attr, char *); static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); static struct w1_family_ops w1_therm_fops = { .rname = &w1_therm_read_name, .rbin = &w1_therm_read_bin, -}; - -static struct w1_family w1_therm_family_DS18S20 = { - .fid = W1_THERM_DS18S20, - .fops = &w1_therm_fops, -}; - -static struct w1_family w1_therm_family_DS18B20 = { - .fid = W1_THERM_DS18B20, - .fops = &w1_therm_fops, -}; -static struct w1_family w1_therm_family_DS1822 = { - .fid = W1_THERM_DS1822, - .fops = &w1_therm_fops, -}; - -struct w1_therm_family_converter -{ - u8 broken; - u16 reserved; - struct w1_family *f; - int (*convert)(u8 rom[9]); -}; - -static inline int w1_DS18B20_convert_temp(u8 rom[9]); -static inline int w1_DS18S20_convert_temp(u8 rom[9]); - -static struct w1_therm_family_converter w1_therm_families[] = { - { - .f = &w1_therm_family_DS18S20, - .convert = w1_DS18S20_convert_temp - }, - { - .f = &w1_therm_family_DS1822, - .convert = w1_DS18B20_convert_temp - }, - { - .f = &w1_therm_family_DS18B20, - .convert = w1_DS18B20_convert_temp - }, + .rval = &w1_therm_read_temp, + .rvalname = "temp1_input", }; static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -97,19 +60,9 @@ static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *a return sprintf(buf, "%s\n", sl->name); } -static inline int w1_DS18B20_convert_temp(u8 rom[9]) -{ - int t = (rom[1] << 8) | rom[0]; - t /= 16; - return t; -} - -static inline int w1_DS18S20_convert_temp(u8 rom[9]) +static inline int w1_convert_temp(u8 rom[9]) { int t, h; - - if (!rom[7]) - return 0; if (rom[1] == 0) t = ((s32)rom[0] >> 1)*1000; @@ -124,15 +77,11 @@ static inline int w1_DS18S20_convert_temp(u8 rom[9]) return t; } -static inline int w1_convert_temp(u8 rom[9], u8 fid) +static ssize_t w1_therm_read_temp(struct device *dev, struct device_attribute *attr, char *buf) { - int i; - - for (i=0; ifid == fid) - return w1_therm_families[i].convert(rom); + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - return 0; + return sprintf(buf, "%d\n", w1_convert_temp(sl->rom)); } static int w1_therm_check_rom(u8 rom[9]) @@ -149,7 +98,7 @@ static int w1_therm_check_rom(u8 rom[9]) static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj), - struct w1_slave, dev); + struct w1_slave, dev); struct w1_master *dev = sl->master; u8 rom[9], crc, verdict; int i, max_trying = 10; @@ -184,7 +133,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si unsigned int tm = 750; memcpy(&match[1], (u64 *) & sl->reg_num, 8); - + w1_write_block(dev, match, 9); w1_write_8(dev, W1_CONVERT_TEMP); @@ -197,7 +146,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si if (!w1_reset_bus (dev)) { w1_write_block(dev, match, 9); - + w1_write_8(dev, W1_READ_SCRATCHPAD); if ((count = w1_read_block(dev, rom, 9)) != 9) { dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count); @@ -227,7 +176,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si for (i = 0; i < 9; ++i) count += sprintf(buf + count, "%02x ", sl->rom[i]); - count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid)); + count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom)); out: up(&dev->mutex); out_dec: @@ -237,26 +186,19 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si return count; } +static struct w1_family w1_therm_family = { + .fid = W1_FAMILY_THERM, + .fops = &w1_therm_fops, +}; + static int __init w1_therm_init(void) { - int err, i; - - for (i=0; i center, 0x12 -> lfe */ unsigned char spdif_bug; /* Has Spdif phasing bug */ unsigned char ac97_chip; /* Has an AC97 chip */ unsigned char ecard; /* APS EEPROM */ - const char *driver; - const char *name; - const char *id; /* for backward compatibility - can be NULL if not needed */ + char * driver; + char * name; } emu_chip_details_t; struct _snd_emu10k1 { int irq; unsigned long port; /* I/O port number */ - unsigned int tos_link: 1, /* tos link detected */ - rear_ac97: 1; /* rear channels are on AC'97 */ + 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 */ + spk71:1; /* 7.1 configuration (Audigy 2 ZS) */ const emu_chip_details_t *card_capabilities; /* Contains profile of card capabilities */ unsigned int audigy; /* is Audigy? */ unsigned int revision; /* chip revision */ @@ -1127,10 +1109,7 @@ struct _snd_emu10k1 { emu10k1_voice_t voices[NUM_G]; emu10k1_voice_t p16v_voices[4]; - emu10k1_voice_t p16v_capture_voice; int p16v_device_offset; - u32 p16v_capture_source; - u32 p16v_capture_channel; emu10k1_pcm_mixer_t pcm_mixer[32]; emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK]; snd_kcontrol_t *ctl_send_routing; @@ -1474,6 +1453,7 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, #endif typedef struct { + unsigned int card; /* card type */ unsigned int internal_tram_size; /* in samples */ unsigned int external_tram_size; /* in samples */ char fxbus_names[16][32]; /* names of FXBUSes */ diff --git a/trunk/include/sound/gus.h b/trunk/include/sound/gus.h index b4b461ca173d..8b6287a6fff5 100644 --- a/trunk/include/sound/gus.h +++ b/trunk/include/sound/gus.h @@ -526,6 +526,9 @@ extern void snd_gf1_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigne extern void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr); extern void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data); extern unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr); +extern void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data); +extern unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr); +extern void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, unsigned short value, unsigned int count); extern void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit); extern unsigned int snd_gf1_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit); extern void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg); @@ -541,6 +544,9 @@ extern inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned cha { return snd_gf1_i_look16(gus, reg | 0x80); } +extern void snd_gf1_i_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data); +extern void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit); +extern unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit); extern void snd_gf1_select_active_voices(snd_gus_card_t * gus); @@ -574,6 +580,10 @@ extern void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char * void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup); int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block); +snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, + unsigned int address); +snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, + unsigned int *share_id); snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner, char *name, int size, int w_16, int align, unsigned int *share_id); @@ -598,13 +608,23 @@ int snd_gf1_dma_transfer_block(snd_gus_card_t * gus, /* gus_volume.c */ unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol); +unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol); +unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus, + unsigned short start, + unsigned short end, + unsigned int us); unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq2); +unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens); +unsigned short snd_gf1_compute_freq(unsigned int freq, + unsigned int rate, + unsigned short mix_rate); /* gus_reset.c */ void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what); void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice); void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice); +void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max); void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max); snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port); void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice); @@ -621,6 +641,9 @@ int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pc #ifdef CONFIG_SND_DEBUG extern void snd_gf1_print_voice_registers(snd_gus_card_t * gus); +extern void snd_gf1_print_global_registers(snd_gus_card_t * gus); +extern void snd_gf1_print_setup_registers(snd_gus_card_t * gus); +extern void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit); #endif /* gus.c */ diff --git a/trunk/include/sound/hdspm.h b/trunk/include/sound/hdspm.h deleted file mode 100644 index c34427ccd0b3..000000000000 --- a/trunk/include/sound/hdspm.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef __SOUND_HDSPM_H /* -*- linux-c -*- */ -#define __SOUND_HDSPM_H -/* - * Copyright (C) 2003 Winfried Ritsch (IEM) - * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ -#define HDSPM_MAX_CHANNELS 64 - -/* -------------------- IOCTL Peak/RMS Meters -------------------- */ - -typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t; - -/* peam rms level structure like we get from hardware - - maybe in future we can memory map it so I just copy it - to user on ioctl call now an dont change anything - rms are made out of low and high values - where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24) - (i asume so from the code) -*/ - -struct _snd_hdspm_peak_rms { - - unsigned int level_offset[1024]; - - unsigned int input_peak[64]; - unsigned int playback_peak[64]; - unsigned int output_peak[64]; - unsigned int xxx_peak[64]; /* not used */ - - unsigned int reserved[256]; /* not used */ - - unsigned int input_rms_l[64]; - unsigned int playback_rms_l[64]; - unsigned int output_rms_l[64]; - unsigned int xxx_rms_l[64]; /* not used */ - - unsigned int input_rms_h[64]; - unsigned int playback_rms_h[64]; - unsigned int output_rms_h[64]; - unsigned int xxx_rms_h[64]; /* not used */ -}; - -struct sndrv_hdspm_peak_rms_ioctl { - hdspm_peak_rms_t *peak; -}; - -/* use indirect access due to the limit of ioctl bit size */ -#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct sndrv_hdspm_peak_rms_ioctl) - -/* ------------ CONFIG block IOCTL ---------------------- */ - -typedef struct _snd_hdspm_config_info hdspm_config_info_t; - -struct _snd_hdspm_config_info { - unsigned char pref_sync_ref; - unsigned char wordclock_sync_check; - unsigned char madi_sync_check; - unsigned int system_sample_rate; - unsigned int autosync_sample_rate; - unsigned char system_clock_mode; - unsigned char clock_source; - unsigned char autosync_ref; - unsigned char line_out; - unsigned int passthru; - unsigned int analog_out; -}; - -#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdspm_config_info_t) - - -/* get Soundcard Version */ - -typedef struct _snd_hdspm_version hdspm_version_t; - -struct _snd_hdspm_version { - unsigned short firmware_rev; -}; - -#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, hdspm_version_t) - - -/* ------------- get Matrix Mixer IOCTL --------------- */ - -/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = 32768 Bytes */ - -/* organisation is 64 channelfader in a continous memory block */ -/* equivalent to hardware definition, maybe for future feature of mmap of them */ -/* each of 64 outputs has 64 infader and 64 outfader: - Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ - -#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS - -typedef struct _snd_hdspm_channelfader snd_hdspm_channelfader_t; - -struct _snd_hdspm_channelfader { - unsigned int in[HDSPM_MIXER_CHANNELS]; - unsigned int pb[HDSPM_MIXER_CHANNELS]; -}; - -typedef struct _snd_hdspm_mixer hdspm_mixer_t; - -struct _snd_hdspm_mixer { - snd_hdspm_channelfader_t ch[HDSPM_MIXER_CHANNELS]; -}; - -struct sndrv_hdspm_mixer_ioctl { - hdspm_mixer_t *mixer; -}; - -/* use indirect access due to the limit of ioctl bit size */ -#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct sndrv_hdspm_mixer_ioctl) - -#endif /* __SOUND_HDSPM_H */ diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h index d935417575b5..53fc04d75bad 100644 --- a/trunk/include/sound/pcm.h +++ b/trunk/include/sound/pcm.h @@ -848,6 +848,23 @@ int snd_interval_ratnum(snd_interval_t *i, void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params); void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var); +int snd_pcm_hw_param_min(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + unsigned int val, int *dir); +int snd_pcm_hw_param_max(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + unsigned int val, int *dir); +int snd_pcm_hw_param_setinteger(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var); +int snd_pcm_hw_param_first(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir); +int snd_pcm_hw_param_last(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir); int snd_pcm_hw_param_near(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var, @@ -859,6 +876,7 @@ int snd_pcm_hw_param_set(snd_pcm_substream_t *pcm, int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params); int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params); +int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params); int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream); int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream); @@ -904,22 +922,8 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format); int snd_pcm_format_linear(snd_pcm_format_t format); int snd_pcm_format_little_endian(snd_pcm_format_t format); int snd_pcm_format_big_endian(snd_pcm_format_t format); -/** - * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian - * @format: the format to check - * - * Returns 1 if the given PCM format is CPU-endian, 0 if - * opposite, or a negative error code if endian not specified. - */ -/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */ -#ifdef SNDRV_LITTLE_ENDIAN -#define snd_pcm_format_cpu_endian snd_pcm_format_little_endian -#else -#define snd_pcm_format_cpu_endian snd_pcm_format_big_endian -#endif int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */ int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */ -ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples); const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format); int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian); diff --git a/trunk/include/sound/seq_midi_event.h b/trunk/include/sound/seq_midi_event.h index 8857e2bd31a5..4357cac07500 100644 --- a/trunk/include/sound/seq_midi_event.h +++ b/trunk/include/sound/seq_midi_event.h @@ -41,7 +41,9 @@ struct snd_midi_event_t { }; int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev); +int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize); void snd_midi_event_free(snd_midi_event_t *dev); +void snd_midi_event_init(snd_midi_event_t *dev); void snd_midi_event_reset_encode(snd_midi_event_t *dev); void snd_midi_event_reset_decode(snd_midi_event_t *dev); void snd_midi_event_no_status(snd_midi_event_t *dev, int on); diff --git a/trunk/include/sound/seq_virmidi.h b/trunk/include/sound/seq_virmidi.h index 1ad27e859af3..cf4e2388103f 100644 --- a/trunk/include/sound/seq_virmidi.h +++ b/trunk/include/sound/seq_virmidi.h @@ -79,5 +79,6 @@ struct _snd_virmidi_dev { #define SNDRV_VIRMIDI_SEQ_DISPATCH 2 int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi); +int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev); #endif /* __SOUND_SEQ_VIRMIDI */ diff --git a/trunk/include/sound/timer.h b/trunk/include/sound/timer.h index 1898511a0f38..57fde990606e 100644 --- a/trunk/include/sound/timer.h +++ b/trunk/include/sound/timer.h @@ -152,4 +152,6 @@ extern int snd_timer_pause(snd_timer_instance_t * timeri); extern void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left); +extern unsigned int snd_timer_system_resolution(void); + #endif /* __SOUND_TIMER_H */ diff --git a/trunk/include/sound/version.h b/trunk/include/sound/version.h index 46acfa8c9988..98b4230778ed 100644 --- a/trunk/include/sound/version.h +++ b/trunk/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.9" -#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)" +#define CONFIG_SND_VERSION "1.0.9rc2" +#define CONFIG_SND_DATE " (Thu Mar 24 10:33:39 2005 UTC)" diff --git a/trunk/net/ipv4/Kconfig b/trunk/net/ipv4/Kconfig index 567b03b1c349..05107e0dc145 100644 --- a/trunk/net/ipv4/Kconfig +++ b/trunk/net/ipv4/Kconfig @@ -2,7 +2,7 @@ # IP configuration # choice - prompt "Choose IP: FIB lookup" + prompt "Choose IP: FIB lookup"" depends on INET default IP_FIB_HASH diff --git a/trunk/sound/Kconfig b/trunk/sound/Kconfig index ee794ae06040..047d59ea0573 100644 --- a/trunk/sound/Kconfig +++ b/trunk/sound/Kconfig @@ -42,11 +42,6 @@ menu "Advanced Linux Sound Architecture" config SND tristate "Advanced Linux Sound Architecture" depends on SOUND - help - Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture), - the new base sound system. - - For more information, see source "sound/core/Kconfig" diff --git a/trunk/sound/arm/Kconfig b/trunk/sound/arm/Kconfig index 34c1740aa6e9..cdacf4d3a387 100644 --- a/trunk/sound/arm/Kconfig +++ b/trunk/sound/arm/Kconfig @@ -14,11 +14,5 @@ config SND_SA11XX_UDA1341 To compile this driver as a module, choose M here: the module will be called snd-sa11xx-uda1341. -config SND_ARMAACI - tristate "ARM PrimeCell PL041 AC Link support" - depends on SND && ARM_AMBA - select SND_PCM - select SND_AC97_CODEC - endmenu diff --git a/trunk/sound/arm/Makefile b/trunk/sound/arm/Makefile index f74ec28e1068..d7e7dc0c3cdf 100644 --- a/trunk/sound/arm/Makefile +++ b/trunk/sound/arm/Makefile @@ -6,6 +6,3 @@ snd-sa11xx-uda1341-objs := sa11xx-uda1341.o # Toplevel Module Dependency obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o - -obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o -snd-aaci-objs := aaci.o devdma.o diff --git a/trunk/sound/arm/aaci.c b/trunk/sound/arm/aaci.c deleted file mode 100644 index 08cc3ddca96f..000000000000 --- a/trunk/sound/arm/aaci.c +++ /dev/null @@ -1,968 +0,0 @@ -/* - * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver - * - * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Documentation: ARM DDI 0173B - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "aaci.h" -#include "devdma.h" - -#define DRIVER_NAME "aaci-pl041" - -/* - * PM support is not complete. Turn it off. - */ -#undef CONFIG_PM - -static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97) -{ - u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num); - - /* - * Ensure that the slot 1/2 RX registers are empty. - */ - v = readl(aaci->base + AACI_SLFR); - if (v & SLFR_2RXV) - readl(aaci->base + AACI_SL2RX); - if (v & SLFR_1RXV) - readl(aaci->base + AACI_SL1RX); - - writel(maincr, aaci->base + AACI_MAINCR); -} - -/* - * P29: - * The recommended use of programming the external codec through slot 1 - * and slot 2 data is to use the channels during setup routines and the - * slot register at any other time. The data written into slot 1, slot 2 - * and slot 12 registers is transmitted only when their corresponding - * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR - * register. - */ -static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) -{ - struct aaci *aaci = ac97->private_data; - u32 v; - - if (ac97->num >= 4) - return; - - down(&aaci->ac97_sem); - - aaci_ac97_select_codec(aaci, ac97); - - /* - * P54: You must ensure that AACI_SL2TX is always written - * to, if required, before data is written to AACI_SL1TX. - */ - writel(val << 4, aaci->base + AACI_SL2TX); - writel(reg << 12, aaci->base + AACI_SL1TX); - - /* - * Wait for the transmission of both slots to complete. - */ - do { - v = readl(aaci->base + AACI_SLFR); - } while (v & (SLFR_1TXB|SLFR_2TXB)); - - up(&aaci->ac97_sem); -} - -/* - * Read an AC'97 register. - */ -static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg) -{ - struct aaci *aaci = ac97->private_data; - u32 v; - - if (ac97->num >= 4) - return ~0; - - down(&aaci->ac97_sem); - - aaci_ac97_select_codec(aaci, ac97); - - /* - * Write the register address to slot 1. - */ - writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); - - /* - * Wait for the transmission to complete. - */ - do { - v = readl(aaci->base + AACI_SLFR); - } while (v & SLFR_1TXB); - - /* - * Give the AC'97 codec more than enough time - * to respond. (42us = ~2 frames at 48kHz.) - */ - udelay(42); - - /* - * Wait for slot 2 to indicate data. - */ - do { - cond_resched(); - v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); - } while (v != (SLFR_1RXV|SLFR_2RXV)); - - v = readl(aaci->base + AACI_SL1RX) >> 12; - if (v == reg) { - v = readl(aaci->base + AACI_SL2RX) >> 4; - } else { - dev_err(&aaci->dev->dev, - "wrong ac97 register read back (%x != %x)\n", - v, reg); - v = ~0; - } - - up(&aaci->ac97_sem); - return v; -} - -static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) -{ - u32 val; - int timeout = 5000; - - do { - val = readl(aacirun->base + AACI_SR); - } while (val & (SR_TXB|SR_RXB) && timeout--); -} - - - -/* - * Interrupt support. - */ -static void aaci_fifo_irq(struct aaci *aaci, u32 mask) -{ - if (mask & ISR_URINTR) { - writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR); - } - - if (mask & ISR_TXINTR) { - struct aaci_runtime *aacirun = &aaci->playback; - void *ptr; - - if (!aacirun->substream || !aacirun->start) { - dev_warn(&aaci->dev->dev, "TX interrupt???"); - writel(0, aacirun->base + AACI_IE); - return; - } - - ptr = aacirun->ptr; - do { - unsigned int len = aacirun->fifosz; - u32 val; - - if (aacirun->bytes <= 0) { - aacirun->bytes += aacirun->period; - aacirun->ptr = ptr; - spin_unlock(&aaci->lock); - snd_pcm_period_elapsed(aacirun->substream); - spin_lock(&aaci->lock); - } - if (!(aacirun->cr & TXCR_TXEN)) - break; - - val = readl(aacirun->base + AACI_SR); - if (!(val & SR_TXHE)) - break; - if (!(val & SR_TXFE)) - len >>= 1; - - aacirun->bytes -= len; - - /* writing 16 bytes at a time */ - for ( ; len > 0; len -= 16) { - asm( - "ldmia %0!, {r0, r1, r2, r3}\n\t" - "stmia %1, {r0, r1, r2, r3}" - : "+r" (ptr) - : "r" (aacirun->fifo) - : "r0", "r1", "r2", "r3", "cc"); - - if (ptr >= aacirun->end) - ptr = aacirun->start; - } - } while (1); - - aacirun->ptr = ptr; - } -} - -static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs) -{ - struct aaci *aaci = devid; - u32 mask; - int i; - - spin_lock(&aaci->lock); - mask = readl(aaci->base + AACI_ALLINTS); - if (mask) { - u32 m = mask; - for (i = 0; i < 4; i++, m >>= 7) { - if (m & 0x7f) { - aaci_fifo_irq(aaci, m); - } - } - } - spin_unlock(&aaci->lock); - - return mask ? IRQ_HANDLED : IRQ_NONE; -} - - - -/* - * ALSA support. - */ - -struct aaci_stream { - unsigned char codec_idx; - unsigned char rate_idx; -}; - -static struct aaci_stream aaci_streams[] = { - [ACSTREAM_FRONT] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_FRONT_DAC, - }, - [ACSTREAM_SURROUND] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_SURR_DAC, - }, - [ACSTREAM_LFE] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_LFE_DAC, - }, -}; - -static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid) -{ - struct aaci_stream *s = aaci_streams + streamid; - return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx]; -} - -static unsigned int rate_list[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 -}; - -/* - * Double-rate rule: we can support double rate iff channels == 2 - * (unimplemented) - */ -static int -aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule) -{ - struct aaci *aaci = rule->private; - unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512; - snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS); - - switch (c->max) { - case 6: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE); - case 4: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND); - case 2: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT); - } - - return snd_interval_list(hw_param_interval(p, rule->var), - ARRAY_SIZE(rate_list), rate_list, - rate_mask); -} - -static snd_pcm_hardware_t aaci_hw_info = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME, - - /* - * ALSA doesn't support 18-bit or 20-bit packed into 32-bit - * words. It also doesn't support 12-bit at all. - */ - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - /* should this be continuous or knot? */ - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_max = 48000, - .rate_min = 4000, - .channels_min = 2, - .channels_max = 6, - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 256, - .period_bytes_max = PAGE_SIZE, - .periods_min = 4, - .periods_max = PAGE_SIZE / 16, -}; - -static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream, - struct aaci_runtime *aacirun) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - int ret; - - aacirun->substream = substream; - runtime->private_data = aacirun; - runtime->hw = aaci_hw_info; - - /* - * FIXME: ALSA specifies fifo_size in bytes. If we're in normal - * mode, each 32-bit word contains one sample. If we're in - * compact mode, each 32-bit word contains two samples, effectively - * halving the FIFO size. However, we don't know for sure which - * we'll be using at this point. We set this to the lower limit. - */ - runtime->hw.fifo_size = aaci->fifosize * 2; - - /* - * Add rule describing hardware rate dependency - * on the number of channels. - */ - ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - aaci_rule_rate_by_channels, aaci, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (ret) - goto out; - - ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT, - DRIVER_NAME, aaci); - if (ret) - goto out; - - return 0; - - out: - return ret; -} - - -/* - * Common ALSA stuff - */ -static int aaci_pcm_close(snd_pcm_substream_t *substream) -{ - struct aaci *aaci = substream->private_data; - struct aaci_runtime *aacirun = substream->runtime->private_data; - - WARN_ON(aacirun->cr & TXCR_TXEN); - - aacirun->substream = NULL; - free_irq(aaci->dev->irq[0], aaci); - - return 0; -} - -static int aaci_pcm_hw_free(snd_pcm_substream_t *substream) -{ - struct aaci_runtime *aacirun = substream->runtime->private_data; - - /* - * This must not be called with the device enabled. - */ - WARN_ON(aacirun->cr & TXCR_TXEN); - - if (aacirun->pcm_open) - snd_ac97_pcm_close(aacirun->pcm); - aacirun->pcm_open = 0; - - /* - * Clear out the DMA and any allocated buffers. - */ - devdma_hw_free(NULL, substream); - - return 0; -} - -static int aaci_pcm_hw_params(snd_pcm_substream_t *substream, - struct aaci_runtime *aacirun, - snd_pcm_hw_params_t *params) -{ - int err; - - aaci_pcm_hw_free(substream); - - err = devdma_hw_alloc(NULL, substream, - params_buffer_bytes(params)); - if (err < 0) - goto out; - - err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), - params_channels(params), - aacirun->pcm->r[0].slots); - if (err) - goto out; - - aacirun->pcm_open = 1; - - out: - return err; -} - -static int aaci_pcm_prepare(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - struct aaci_runtime *aacirun = runtime->private_data; - - aacirun->start = (void *)runtime->dma_area; - aacirun->end = aacirun->start + runtime->dma_bytes; - aacirun->ptr = aacirun->start; - aacirun->period = - aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); - - return 0; -} - -static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - struct aaci_runtime *aacirun = runtime->private_data; - ssize_t bytes = aacirun->ptr - aacirun->start; - - return bytes_to_frames(runtime, bytes); -} - -static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma) -{ - return devdma_mmap(NULL, substream, vma); -} - - -/* - * Playback specific ALSA stuff - */ -static const u32 channels_to_txmask[] = { - [2] = TXCR_TX3 | TXCR_TX4, - [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8, - [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9, -}; - -/* - * We can support two and four channel audio. Unfortunately - * six channel audio requires a non-standard channel ordering: - * 2 -> FL(3), FR(4) - * 4 -> FL(3), FR(4), SL(7), SR(8) - * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) - * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) - * This requires an ALSA configuration file to correct. - */ -static unsigned int channel_list[] = { 2, 4, 6 }; - -static int -aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule) -{ - struct aaci *aaci = rule->private; - unsigned int chan_mask = 1 << 0, slots; - - /* - * pcms[0] is the our 5.1 PCM instance. - */ - slots = aaci->ac97_bus->pcms[0].r[0].slots; - if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { - chan_mask |= 1 << 1; - if (slots & (1 << AC97_SLOT_LFE)) - chan_mask |= 1 << 2; - } - - return snd_interval_list(hw_param_interval(p, rule->var), - ARRAY_SIZE(channel_list), channel_list, - chan_mask); -} - -static int aaci_pcm_playback_open(snd_pcm_substream_t *substream) -{ - struct aaci *aaci = substream->private_data; - int ret; - - /* - * Add rule describing channel dependency. - */ - ret = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - aaci_rule_channels, aaci, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (ret) - return ret; - - return aaci_pcm_open(aaci, substream, &aaci->playback); -} - -static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t *params) -{ - struct aaci *aaci = substream->private_data; - struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned int channels = params_channels(params); - int ret; - - WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) || - !channels_to_txmask[channels]); - - ret = aaci_pcm_hw_params(substream, aacirun, params); - - /* - * Enable FIFO, compact mode, 16 bits per sample. - * FIXME: double rate slots? - */ - if (ret >= 0) { - aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16; - aacirun->cr |= channels_to_txmask[channels]; - - aacirun->fifosz = aaci->fifosize * 4; - if (aacirun->cr & TXCR_COMPACT) - aacirun->fifosz >>= 1; - } - return ret; -} - -static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) -{ - u32 ie; - - ie = readl(aacirun->base + AACI_IE); - ie &= ~(IE_URIE|IE_TXIE); - writel(ie, aacirun->base + AACI_IE); - aacirun->cr &= ~TXCR_TXEN; - aaci_chan_wait_ready(aacirun); - writel(aacirun->cr, aacirun->base + AACI_TXCR); -} - -static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) -{ - u32 ie; - - aaci_chan_wait_ready(aacirun); - aacirun->cr |= TXCR_TXEN; - - ie = readl(aacirun->base + AACI_IE); - ie |= IE_URIE | IE_TXIE; - writel(ie, aacirun->base + AACI_IE); - writel(aacirun->cr, aacirun->base + AACI_TXCR); -} - -static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd) -{ - struct aaci *aaci = substream->private_data; - struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&aaci->lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - aaci_pcm_playback_start(aacirun); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - aaci_pcm_playback_start(aacirun); - break; - - case SNDRV_PCM_TRIGGER_STOP: - aaci_pcm_playback_stop(aacirun); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - aaci_pcm_playback_stop(aacirun); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - break; - - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&aaci->lock, flags); - - return ret; -} - -static snd_pcm_ops_t aaci_playback_ops = { - .open = aaci_pcm_playback_open, - .close = aaci_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = aaci_pcm_playback_hw_params, - .hw_free = aaci_pcm_hw_free, - .prepare = aaci_pcm_prepare, - .trigger = aaci_pcm_playback_trigger, - .pointer = aaci_pcm_pointer, - .mmap = aaci_pcm_mmap, -}; - - - -/* - * Power Management. - */ -#ifdef CONFIG_PM -static int aaci_do_suspend(snd_card_t *card, unsigned int state) -{ - struct aaci *aaci = card->private_data; - if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) { - snd_pcm_suspend_all(aaci->pcm); - snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold); - } - return 0; -} - -static int aaci_do_resume(snd_card_t *card, unsigned int state) -{ - struct aaci *aaci = card->private_data; - if (aaci->card->power_state != SNDRV_CTL_POWER_D0) { - snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0); - } - return 0; -} - -static int aaci_suspend(struct amba_device *dev, u32 state) -{ - snd_card_t *card = amba_get_drvdata(dev); - return card ? aaci_do_suspend(card) : 0; -} - -static int aaci_resume(struct amba_device *dev) -{ - snd_card_t *card = amba_get_drvdata(dev); - return card ? aaci_do_resume(card) : 0; -} -#else -#define aaci_do_suspend NULL -#define aaci_do_resume NULL -#define aaci_suspend NULL -#define aaci_resume NULL -#endif - - -static struct ac97_pcm ac97_defs[] __devinitdata = { - [0] = { /* Front PCM */ - .exclusive = 1, - .r = { - [0] = { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) | - (1 << AC97_SLOT_PCM_CENTER) | - (1 << AC97_SLOT_PCM_SLEFT) | - (1 << AC97_SLOT_PCM_SRIGHT) | - (1 << AC97_SLOT_LFE), - }, - }, - }, - [1] = { /* PCM in */ - .stream = 1, - .exclusive = 1, - .r = { - [0] = { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT), - }, - }, - }, - [2] = { /* Mic in */ - .stream = 1, - .exclusive = 1, - .r = { - [0] = { - .slots = (1 << AC97_SLOT_MIC), - }, - }, - } -}; - -static ac97_bus_ops_t aaci_bus_ops = { - .write = aaci_ac97_write, - .read = aaci_ac97_read, -}; - -static int __devinit aaci_probe_ac97(struct aaci *aaci) -{ - ac97_template_t ac97_template; - ac97_bus_t *ac97_bus; - ac97_t *ac97; - int ret; - - /* - * Assert AACIRESET for 2us - */ - writel(0, aaci->base + AACI_RESET); - udelay(2); - writel(RESET_NRST, aaci->base + AACI_RESET); - - /* - * Give the AC'97 codec more than enough time - * to wake up. (42us = ~2 frames at 48kHz.) - */ - udelay(42); - - ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); - if (ret) - goto out; - - ac97_bus->clock = 48000; - aaci->ac97_bus = ac97_bus; - - memset(&ac97_template, 0, sizeof(ac97_template_t)); - ac97_template.private_data = aaci; - ac97_template.num = 0; - ac97_template.scaps = AC97_SCAP_SKIP_MODEM; - - ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); - if (ret) - goto out; - - /* - * Disable AC97 PC Beep input on audio codecs. - */ - if (ac97_is_audio(ac97)) - snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); - - ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs); - if (ret) - goto out; - - aaci->playback.pcm = &ac97_bus->pcms[0]; - - out: - return ret; -} - -static void aaci_free_card(snd_card_t *card) -{ - struct aaci *aaci = card->private_data; - if (aaci->base) - iounmap(aaci->base); -} - -static struct aaci * __devinit aaci_init_card(struct amba_device *dev) -{ - struct aaci *aaci; - snd_card_t *card; - - card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct aaci)); - if (card == NULL) - return ERR_PTR(-ENOMEM); - - card->private_free = aaci_free_card; - snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL); - - strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); - strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%08lx, irq %d", - card->shortname, dev->res.start, dev->irq[0]); - - aaci = card->private_data; - init_MUTEX(&aaci->ac97_sem); - spin_lock_init(&aaci->lock); - aaci->card = card; - aaci->dev = dev; - - /* Set MAINCR to allow slot 1 and 2 data IO */ - aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN | - MAINCR_SL2RXEN | MAINCR_SL2TXEN; - - return aaci; -} - -static int __devinit aaci_init_pcm(struct aaci *aaci) -{ - snd_pcm_t *pcm; - int ret; - - ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm); - if (ret == 0) { - aaci->pcm = pcm; - pcm->private_data = aaci; - pcm->info_flags = 0; - - strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); - } - - return ret; -} - -static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) -{ - void *base = aaci->base + AACI_CSCH1; - int i; - - writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR); - - for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++) - writel(0, aaci->base + AACI_DR1); - - writel(0, base + AACI_TXCR); - - /* - * Re-initialise the AACI after the FIFO depth test, to - * ensure that the FIFOs are empty. Unfortunately, merely - * disabling the channel doesn't clear the FIFO. - */ - writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); - writel(aaci->maincr, aaci->base + AACI_MAINCR); - - /* - * If we hit 4096, we failed. Go back to the specified - * fifo depth. - */ - if (i == 4096) - i = 8; - - return i; -} - -static int __devinit aaci_probe(struct amba_device *dev, void *id) -{ - struct aaci *aaci; - int ret, i; - - ret = amba_request_regions(dev, NULL); - if (ret) - return ret; - - aaci = aaci_init_card(dev); - if (IS_ERR(aaci)) { - ret = PTR_ERR(aaci); - goto out; - } - - aaci->base = ioremap(dev->res.start, SZ_4K); - if (!aaci->base) { - ret = -ENOMEM; - goto out; - } - - /* - * Playback uses AACI channel 0 - */ - aaci->playback.base = aaci->base + AACI_CSCH1; - aaci->playback.fifo = aaci->base + AACI_DR1; - - for (i = 0; i < 4; i++) { - void *base = aaci->base + i * 0x14; - - writel(0, base + AACI_IE); - writel(0, base + AACI_TXCR); - writel(0, base + AACI_RXCR); - } - - writel(0x1fff, aaci->base + AACI_INTCLR); - writel(aaci->maincr, aaci->base + AACI_MAINCR); - - /* - * Size the FIFOs. - */ - aaci->fifosize = aaci_size_fifo(aaci); - - ret = aaci_probe_ac97(aaci); - if (ret) - goto out; - - ret = aaci_init_pcm(aaci); - if (ret) - goto out; - - ret = snd_card_register(aaci->card); - if (ret == 0) { - dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname, - aaci->fifosize); - amba_set_drvdata(dev, aaci->card); - return ret; - } - - out: - if (aaci) - snd_card_free(aaci->card); - amba_release_regions(dev); - return ret; -} - -static int __devexit aaci_remove(struct amba_device *dev) -{ - snd_card_t *card = amba_get_drvdata(dev); - - amba_set_drvdata(dev, NULL); - - if (card) { - struct aaci *aaci = card->private_data; - writel(0, aaci->base + AACI_MAINCR); - - snd_card_free(card); - amba_release_regions(dev); - } - - return 0; -} - -static struct amba_id aaci_ids[] = { - { - .id = 0x00041041, - .mask = 0x000fffff, - }, - { 0, 0 }, -}; - -static struct amba_driver aaci_driver = { - .drv = { - .name = DRIVER_NAME, - }, - .probe = aaci_probe, - .remove = __devexit_p(aaci_remove), - .suspend = aaci_suspend, - .resume = aaci_resume, - .id_table = aaci_ids, -}; - -static int __init aaci_init(void) -{ - return amba_driver_register(&aaci_driver); -} - -static void __exit aaci_exit(void) -{ - amba_driver_unregister(&aaci_driver); -} - -module_init(aaci_init); -module_exit(aaci_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver"); diff --git a/trunk/sound/arm/aaci.h b/trunk/sound/arm/aaci.h deleted file mode 100644 index d752e6426894..000000000000 --- a/trunk/sound/arm/aaci.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver - * - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef AACI_H -#define AACI_H - -/* - * Control and status register offsets - * P39. - */ -#define AACI_CSCH1 0x000 -#define AACI_CSCH2 0x014 -#define AACI_CSCH3 0x028 -#define AACI_CSCH4 0x03c - -#define AACI_RXCR 0x000 /* 29 bits Control Rx FIFO */ -#define AACI_TXCR 0x004 /* 17 bits Control Tx FIFO */ -#define AACI_SR 0x008 /* 12 bits Status */ -#define AACI_ISR 0x00c /* 7 bits Int Status */ -#define AACI_IE 0x010 /* 7 bits Int Enable */ - -/* - * Other registers - */ -#define AACI_SL1RX 0x050 -#define AACI_SL1TX 0x054 -#define AACI_SL2RX 0x058 -#define AACI_SL2TX 0x05c -#define AACI_SL12RX 0x060 -#define AACI_SL12TX 0x064 -#define AACI_SLFR 0x068 /* slot flags */ -#define AACI_SLISTAT 0x06c /* slot interrupt status */ -#define AACI_SLIEN 0x070 /* slot interrupt enable */ -#define AACI_INTCLR 0x074 /* interrupt clear */ -#define AACI_MAINCR 0x078 /* main control */ -#define AACI_RESET 0x07c /* reset control */ -#define AACI_SYNC 0x080 /* sync control */ -#define AACI_ALLINTS 0x084 /* all fifo interrupt status */ -#define AACI_MAINFR 0x088 /* main flag register */ -#define AACI_DR1 0x090 /* data read/written fifo 1 */ -#define AACI_DR2 0x0b0 /* data read/written fifo 2 */ -#define AACI_DR3 0x0d0 /* data read/written fifo 3 */ -#define AACI_DR4 0x0f0 /* data read/written fifo 4 */ - -/* - * transmit fifo control register. P48 - */ -#define TXCR_FEN (1 << 16) /* fifo enable */ -#define TXCR_COMPACT (1 << 15) /* compact mode */ -#define TXCR_TSZ16 (0 << 13) /* 16 bits */ -#define TXCR_TSZ18 (1 << 13) /* 18 bits */ -#define TXCR_TSZ20 (2 << 13) /* 20 bits */ -#define TXCR_TSZ12 (3 << 13) /* 12 bits */ -#define TXCR_TX12 (1 << 12) /* transmits slot 12 */ -#define TXCR_TX11 (1 << 11) /* transmits slot 12 */ -#define TXCR_TX10 (1 << 10) /* transmits slot 12 */ -#define TXCR_TX9 (1 << 9) /* transmits slot 12 */ -#define TXCR_TX8 (1 << 8) /* transmits slot 12 */ -#define TXCR_TX7 (1 << 7) /* transmits slot 12 */ -#define TXCR_TX6 (1 << 6) /* transmits slot 12 */ -#define TXCR_TX5 (1 << 5) /* transmits slot 12 */ -#define TXCR_TX4 (1 << 4) /* transmits slot 12 */ -#define TXCR_TX3 (1 << 3) /* transmits slot 12 */ -#define TXCR_TX2 (1 << 2) /* transmits slot 12 */ -#define TXCR_TX1 (1 << 1) /* transmits slot 12 */ -#define TXCR_TXEN (1 << 0) /* transmit enable */ - -/* - * status register bits. P49 - */ -#define SR_RXTOFE (1 << 11) /* rx timeout fifo empty */ -#define SR_TXTO (1 << 10) /* rx timeout fifo nonempty */ -#define SR_TXU (1 << 9) /* tx underrun */ -#define SR_RXO (1 << 8) /* rx overrun */ -#define SR_TXB (1 << 7) /* tx busy */ -#define SR_RXB (1 << 6) /* rx busy */ -#define SR_TXFF (1 << 5) /* tx fifo full */ -#define SR_RXFF (1 << 4) /* rx fifo full */ -#define SR_TXHE (1 << 3) /* tx fifo half empty */ -#define SR_RXHF (1 << 2) /* rx fifo half full */ -#define SR_TXFE (1 << 1) /* tx fifo empty */ -#define SR_RXFE (1 << 0) /* rx fifo empty */ - -/* - * interrupt status register bits. - */ -#define ISR_RXTOFEINTR (1 << 6) /* rx fifo empty */ -#define ISR_URINTR (1 << 5) /* tx underflow */ -#define ISR_ORINTR (1 << 4) /* rx overflow */ -#define ISR_RXINTR (1 << 3) /* rx fifo */ -#define ISR_TXINTR (1 << 2) /* tx fifo intr */ -#define ISR_RXTOINTR (1 << 1) /* tx timeout */ -#define ISR_TXCINTR (1 << 0) /* tx complete */ - -/* - * interrupt enable register bits. - */ -#define IE_RXTOIE (1 << 6) -#define IE_URIE (1 << 5) -#define IE_ORIE (1 << 4) -#define IE_RXIE (1 << 3) -#define IE_TXIE (1 << 2) -#define IE_RXTIE (1 << 1) -#define IE_TXCIE (1 << 0) - -/* - * interrupt status. P51 - */ -#define ISR_RXTOFE (1 << 6) /* rx timeout fifo empty */ -#define ISR_UR (1 << 5) /* tx fifo underrun */ -#define ISR_OR (1 << 4) /* rx fifo overrun */ -#define ISR_RX (1 << 3) /* rx interrupt status */ -#define ISR_TX (1 << 2) /* tx interrupt status */ -#define ISR_RXTO (1 << 1) /* rx timeout */ -#define ISR_TXC (1 << 0) /* tx complete */ - -/* - * interrupt enable. P52 - */ -#define IE_RXTOFE (1 << 6) /* rx timeout fifo empty */ -#define IE_UR (1 << 5) /* tx fifo underrun */ -#define IE_OR (1 << 4) /* rx fifo overrun */ -#define IE_RX (1 << 3) /* rx interrupt status */ -#define IE_TX (1 << 2) /* tx interrupt status */ -#define IE_RXTO (1 << 1) /* rx timeout */ -#define IE_TXC (1 << 0) /* tx complete */ - -/* - * slot flag register bits. P56 - */ -#define SLFR_RWIS (1 << 13) /* raw wake-up interrupt status */ -#define SLFR_RGPIOINTR (1 << 12) /* raw gpio interrupt */ -#define SLFR_12TXE (1 << 11) /* slot 12 tx empty */ -#define SLFR_12RXV (1 << 10) /* slot 12 rx valid */ -#define SLFR_2TXE (1 << 9) /* slot 2 tx empty */ -#define SLFR_2RXV (1 << 8) /* slot 2 rx valid */ -#define SLFR_1TXE (1 << 7) /* slot 1 tx empty */ -#define SLFR_1RXV (1 << 6) /* slot 1 rx valid */ -#define SLFR_12TXB (1 << 5) /* slot 12 tx busy */ -#define SLFR_12RXB (1 << 4) /* slot 12 rx busy */ -#define SLFR_2TXB (1 << 3) /* slot 2 tx busy */ -#define SLFR_2RXB (1 << 2) /* slot 2 rx busy */ -#define SLFR_1TXB (1 << 1) /* slot 1 tx busy */ -#define SLFR_1RXB (1 << 0) /* slot 1 rx busy */ - -/* - * Interrupt clear register. - */ -#define ICLR_RXTOFEC4 (1 << 12) -#define ICLR_RXTOFEC3 (1 << 11) -#define ICLR_RXTOFEC2 (1 << 10) -#define ICLR_RXTOFEC1 (1 << 9) -#define ICLR_TXUEC4 (1 << 8) -#define ICLR_TXUEC3 (1 << 7) -#define ICLR_TXUEC2 (1 << 6) -#define ICLR_TXUEC1 (1 << 5) -#define ICLR_RXOEC4 (1 << 4) -#define ICLR_RXOEC3 (1 << 3) -#define ICLR_RXOEC2 (1 << 2) -#define ICLR_RXOEC1 (1 << 1) -#define ICLR_WISC (1 << 0) - -/* - * Main control register bits. P62 - */ -#define MAINCR_SCRA(x) ((x) << 10) /* secondary codec reg access */ -#define MAINCR_DMAEN (1 << 9) /* dma enable */ -#define MAINCR_SL12TXEN (1 << 8) /* slot 12 transmit enable */ -#define MAINCR_SL12RXEN (1 << 7) /* slot 12 receive enable */ -#define MAINCR_SL2TXEN (1 << 6) /* slot 2 transmit enable */ -#define MAINCR_SL2RXEN (1 << 5) /* slot 2 receive enable */ -#define MAINCR_SL1TXEN (1 << 4) /* slot 1 transmit enable */ -#define MAINCR_SL1RXEN (1 << 3) /* slot 1 receive enable */ -#define MAINCR_LPM (1 << 2) /* low power mode */ -#define MAINCR_LOOPBK (1 << 1) /* loopback */ -#define MAINCR_IE (1 << 0) /* aaci interface enable */ - -/* - * Reset register bits. P65 - */ -#define RESET_NRST (1 << 0) - -/* - * Sync register bits. P65 - */ -#define SYNC_FORCE (1 << 0) - -/* - * Main flag register bits. P66 - */ -#define MAINFR_TXB (1 << 1) /* transmit busy */ -#define MAINFR_RXB (1 << 0) /* receive busy */ - - - -struct aaci_runtime { - void *base; - void *fifo; - - struct ac97_pcm *pcm; - int pcm_open; - - u32 cr; - snd_pcm_substream_t *substream; - - /* - * PIO support - */ - void *start; - void *end; - void *ptr; - int bytes; - unsigned int period; - unsigned int fifosz; -}; - -struct aaci { - struct amba_device *dev; - snd_card_t *card; - void *base; - unsigned int fifosize; - - /* AC'97 */ - struct semaphore ac97_sem; - ac97_bus_t *ac97_bus; - - u32 maincr; - spinlock_t lock; - - struct aaci_runtime playback; - struct aaci_runtime capture; - - snd_pcm_t *pcm; -}; - -#define ACSTREAM_FRONT 0 -#define ACSTREAM_SURROUND 1 -#define ACSTREAM_LFE 2 - -#endif diff --git a/trunk/sound/arm/devdma.c b/trunk/sound/arm/devdma.c deleted file mode 100644 index 60826a5324b4..000000000000 --- a/trunk/sound/arm/devdma.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * linux/sound/arm/devdma.c - * - * Copyright (C) 2003-2004 Russell King, All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ARM DMA shim for ALSA. - */ -#include -#include - -#include -#include -#include - -#include "devdma.h" - -void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - struct snd_dma_buffer *buf = runtime->dma_buffer_p; - - if (runtime->dma_area == NULL) - return; - - if (buf != &substream->dma_buffer) { - dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); - kfree(runtime->dma_buffer_p); - } - - snd_pcm_set_runtime_buffer(substream, NULL); -} - -int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - struct snd_dma_buffer *buf = runtime->dma_buffer_p; - int ret = 0; - - if (buf) { - if (buf->bytes >= size) - goto out; - devdma_hw_free(dev, substream); - } - - if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { - buf = &substream->dma_buffer; - } else { - buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); - if (!buf) - goto nomem; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = dev; - buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); - buf->bytes = size; - buf->private_data = NULL; - - if (!buf->area) - goto free; - } - snd_pcm_set_runtime_buffer(substream, buf); - ret = 1; - out: - runtime->dma_bytes = size; - return ret; - - free: - kfree(buf); - nomem: - return -ENOMEM; -} - -int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); -} diff --git a/trunk/sound/arm/devdma.h b/trunk/sound/arm/devdma.h deleted file mode 100644 index 5a33b6bacc34..000000000000 --- a/trunk/sound/arm/devdma.h +++ /dev/null @@ -1,3 +0,0 @@ -void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream); -int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size); -int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma); diff --git a/trunk/sound/core/control.c b/trunk/sound/core/control.c index 227f3cf02771..f4ea6bff1dd3 100644 --- a/trunk/sound/core/control.c +++ b/trunk/sound/core/control.c @@ -215,7 +215,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access) * * Returns the pointer of the newly generated instance, or NULL on failure. */ -snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data) +snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data) { snd_kcontrol_t kctl; unsigned int access; @@ -1102,7 +1102,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg } } up_read(&snd_ioctl_rwsem); - snd_printdd("unknown ioctl = 0x%x\n", cmd); + snd_printd("unknown ioctl = 0x%x\n", cmd); return -ENOTTY; } diff --git a/trunk/sound/core/memalloc.c b/trunk/sound/core/memalloc.c index dbc23e35fa06..344a83fd7c2e 100644 --- a/trunk/sound/core/memalloc.c +++ b/trunk/sound/core/memalloc.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +46,13 @@ MODULE_LICENSE("GPL"); #define SNDRV_CARDS 8 #endif +/* FIXME: so far only some PCI devices have the preallocation table */ +#ifdef CONFIG_PCI +static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable cards to allocate buffers."); +#endif + /* */ @@ -445,13 +451,9 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) list_for_each(p, &mem_list_head) { mem = list_entry(p, struct snd_mem_list, list); if (mem->id == id && - (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL || - ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) { - struct device *dev = dmab->dev.dev; + ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) { list_del(p); *dmab = mem->buffer; - if (dmab->dev.dev == NULL) - dmab->dev.dev = dev; kfree(mem); up(&list_mutex); return dmab->bytes; @@ -506,13 +508,91 @@ static void free_all_reserved_pages(void) } + +/* + * allocation of buffers for pre-defined devices + */ + +#ifdef CONFIG_PCI +/* FIXME: for pci only - other bus? */ +struct prealloc_dev { + unsigned short vendor; + unsigned short device; + unsigned long dma_mask; + unsigned int size; + unsigned int buffers; +}; + +#define HAMMERFALL_BUFFER_SIZE (16*1024*4*(26+1)+0x10000) + +static struct prealloc_dev prealloc_devices[] __initdata = { + { + /* hammerfall */ + .vendor = 0x10ee, + .device = 0x3fc4, + .dma_mask = 0xffffffff, + .size = HAMMERFALL_BUFFER_SIZE, + .buffers = 2 + }, + { + /* HDSP */ + .vendor = 0x10ee, + .device = 0x3fc5, + .dma_mask = 0xffffffff, + .size = HAMMERFALL_BUFFER_SIZE, + .buffers = 2 + }, + { }, /* terminator */ +}; + +static void __init preallocate_cards(void) +{ + struct pci_dev *pci = NULL; + int card; + + card = 0; + + while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) { + struct prealloc_dev *dev; + unsigned int i; + if (card >= SNDRV_CARDS) + break; + for (dev = prealloc_devices; dev->vendor; dev++) { + if (dev->vendor == pci->vendor && dev->device == pci->device) + break; + } + if (! dev->vendor) + continue; + if (! enable[card++]) { + printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device); + continue; + } + + if (pci_set_dma_mask(pci, dev->dma_mask) < 0 || + pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) { + printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device); + continue; + } + for (i = 0; i < dev->buffers; i++) { + struct snd_dma_buffer dmab; + memset(&dmab, 0, sizeof(dmab)); + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), + dev->size, &dmab) < 0) + printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size); + else + snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); + } + } +} +#else +#define preallocate_cards() /* NOP */ +#endif + + #ifdef CONFIG_PROC_FS /* * proc file interface */ -#define SND_MEM_PROC_FILE "driver/snd-page-alloc" -struct proc_dir_entry *snd_mem_proc; - static int snd_mem_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -541,97 +621,6 @@ static int snd_mem_proc_read(char *page, char **start, off_t off, up(&list_mutex); return len; } - -/* FIXME: for pci only - other bus? */ -#ifdef CONFIG_PCI -#define gettoken(bufp) strsep(bufp, " \t\n") - -static int snd_mem_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - char buf[128]; - char *token, *p; - - if (count > ARRAY_SIZE(buf) - 1) - count = ARRAY_SIZE(buf) - 1; - if (copy_from_user(buf, buffer, count)) - return -EFAULT; - buf[ARRAY_SIZE(buf) - 1] = '\0'; - - p = buf; - token = gettoken(&p); - if (! token || *token == '#') - return (int)count; - if (strcmp(token, "add") == 0) { - char *endp; - int vendor, device, size, buffers; - long mask; - int i, alloced; - struct pci_dev *pci; - - if ((token = gettoken(&p)) == NULL || - (vendor = simple_strtol(token, NULL, 0)) <= 0 || - (token = gettoken(&p)) == NULL || - (device = simple_strtol(token, NULL, 0)) <= 0 || - (token = gettoken(&p)) == NULL || - (mask = simple_strtol(token, NULL, 0)) < 0 || - (token = gettoken(&p)) == NULL || - (size = memparse(token, &endp)) < 64*1024 || - size > 16*1024*1024 /* too big */ || - (token = gettoken(&p)) == NULL || - (buffers = simple_strtol(token, NULL, 0)) <= 0 || - buffers > 4) { - printk(KERN_ERR "snd-page-alloc: invalid proc write format\n"); - return (int)count; - } - vendor &= 0xffff; - device &= 0xffff; - - alloced = 0; - pci = NULL; - while ((pci = pci_find_device(vendor, device, pci)) != NULL) { - if (mask > 0 && mask < 0xffffffff) { - if (pci_set_dma_mask(pci, mask) < 0 || - pci_set_consistent_dma_mask(pci, mask) < 0) { - printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device); - return (int)count; - } - } - for (i = 0; i < buffers; i++) { - struct snd_dma_buffer dmab; - memset(&dmab, 0, sizeof(dmab)); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &dmab) < 0) { - printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); - return (int)count; - } - snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); - } - alloced++; - } - if (! alloced) { - for (i = 0; i < buffers; i++) { - struct snd_dma_buffer dmab; - memset(&dmab, 0, sizeof(dmab)); - /* FIXME: We can allocate only in ZONE_DMA - * without a device pointer! - */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL, - size, &dmab) < 0) { - printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); - break; - } - snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device)); - } - } - } else if (strcmp(token, "erase") == 0) - /* FIXME: need for releasing each buffer chunk? */ - free_all_reserved_pages(); - else - printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n"); - return (int)count; -} -#endif /* CONFIG_PCI */ #endif /* CONFIG_PROC_FS */ /* @@ -641,21 +630,15 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer, static int __init snd_mem_init(void) { #ifdef CONFIG_PROC_FS - snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL); - if (snd_mem_proc) { - snd_mem_proc->read_proc = snd_mem_proc_read; -#ifdef CONFIG_PCI - snd_mem_proc->write_proc = snd_mem_proc_write; -#endif - } + create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL); #endif + preallocate_cards(); return 0; } static void __exit snd_mem_exit(void) { - if (snd_mem_proc) - remove_proc_entry(SND_MEM_PROC_FILE, NULL); + remove_proc_entry("driver/snd-page-alloc", NULL); free_all_reserved_pages(); if (snd_allocated_pages > 0) printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages); diff --git a/trunk/sound/core/oss/pcm_oss.c b/trunk/sound/core/oss/pcm_oss.c index cab30977e7c0..1a805020f57a 100644 --- a/trunk/sound/core/oss/pcm_oss.c +++ b/trunk/sound/core/oss/pcm_oss.c @@ -125,26 +125,17 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin) static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames) { snd_pcm_runtime_t *runtime = substream->runtime; - long buffer_size = snd_pcm_lib_buffer_bytes(substream); - long bytes = frames_to_bytes(runtime, frames); + snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); + frames = frames_to_bytes(runtime, frames); if (buffer_size == runtime->oss.buffer_bytes) - return bytes; -#if BITS_PER_LONG >= 64 - return runtime->oss.buffer_bytes * bytes / buffer_size; -#else - { - u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; - u32 rem; - div64_32(&bsize, buffer_size, &rem); - return (long)bsize; - } -#endif + return frames; + return (runtime->oss.buffer_bytes * frames) / buffer_size; } static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes) { snd_pcm_runtime_t *runtime = substream->runtime; - long buffer_size = snd_pcm_lib_buffer_bytes(substream); + snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); if (buffer_size == runtime->oss.buffer_bytes) return bytes_to_frames(runtime, bytes); return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); @@ -473,8 +464,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; sw_params->period_step = 1; sw_params->sleep_min = 0; - sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - 1 : runtime->period_size; + sw_params->avail_min = 1; sw_params->xfer_align = 1; if (atomic_read(&runtime->mmap_count) || (substream->oss.setup && substream->oss.setup->nosilence)) { @@ -1537,15 +1527,12 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str snd_pcm_oss_simulate_fill(substream, delay); info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; } else { - delay = snd_pcm_oss_bytes(substream, delay); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; + delay = snd_pcm_oss_bytes(substream, delay) + fixup; + info.blocks = delay / runtime->oss.period_bytes; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) info.bytes = (runtime->oss.bytes - delay) & INT_MAX; - } else { - delay += fixup; - info.blocks = delay / runtime->oss.period_bytes; + else info.bytes = (runtime->oss.bytes + delay) & INT_MAX; - } } if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; diff --git a/trunk/sound/core/oss/pcm_plugin.c b/trunk/sound/core/oss/pcm_plugin.c index 6430410c6c04..6bb31009f0b4 100644 --- a/trunk/sound/core/oss/pcm_plugin.c +++ b/trunk/sound/core/oss/pcm_plugin.c @@ -663,7 +663,10 @@ static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, bitset_t *dstmask = bs; int err; bitset_one(dstmask, schannels); - + if (plugin == NULL) { + bitset_and(client_vmask, dstmask, schannels); + return 0; + } while (1) { err = plugin->src_channels_mask(plugin, dstmask, &srcmask); if (err < 0) diff --git a/trunk/sound/core/pcm.c b/trunk/sound/core/pcm.c index 9f4c9209b271..8d94325529a8 100644 --- a/trunk/sound/core/pcm.c +++ b/trunk/sound/core/pcm.c @@ -451,7 +451,6 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr) entry->c.text.read = snd_pcm_xrun_debug_read; entry->c.text.write_size = 64; entry->c.text.write = snd_pcm_xrun_debug_write; - entry->mode |= S_IWUSR; entry->private_data = pstr; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); @@ -1049,6 +1048,7 @@ EXPORT_SYMBOL(snd_pcm_release_substream); EXPORT_SYMBOL(snd_pcm_format_name); /* pcm_native.c */ EXPORT_SYMBOL(snd_pcm_link_rwlock); +EXPORT_SYMBOL(snd_pcm_start); #ifdef CONFIG_PM EXPORT_SYMBOL(snd_pcm_suspend); EXPORT_SYMBOL(snd_pcm_suspend_all); @@ -1068,7 +1068,6 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian); EXPORT_SYMBOL(snd_pcm_format_big_endian); EXPORT_SYMBOL(snd_pcm_format_width); EXPORT_SYMBOL(snd_pcm_format_physical_width); -EXPORT_SYMBOL(snd_pcm_format_size); EXPORT_SYMBOL(snd_pcm_format_silence_64); EXPORT_SYMBOL(snd_pcm_format_set_silence); EXPORT_SYMBOL(snd_pcm_build_linear_format); diff --git a/trunk/sound/core/pcm_lib.c b/trunk/sound/core/pcm_lib.c index c5bfd0918cff..151fd99ca2c9 100644 --- a/trunk/sound/core/pcm_lib.c +++ b/trunk/sound/core/pcm_lib.c @@ -1143,8 +1143,7 @@ int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime, #define INT_MIN ((int)((unsigned int)INT_MAX+1)) #endif -static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var) +void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var) { if (hw_is_mask(var)) { snd_mask_any(hw_param_mask(params, var)); @@ -1161,7 +1160,6 @@ static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_BUG(); } -#if 0 /** * snd_pcm_hw_param_any */ @@ -1171,7 +1169,6 @@ int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, _snd_pcm_hw_param_any(params, var); return snd_pcm_hw_refine(pcm, params); } -#endif /* 0 */ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) { @@ -1184,7 +1181,6 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) params->info = ~0U; } -#if 0 /** * snd_pcm_hw_params_any * @@ -1195,7 +1191,6 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) _snd_pcm_hw_params_any(params); return snd_pcm_hw_refine(pcm, params); } -#endif /* 0 */ /** * snd_pcm_hw_param_value @@ -1203,8 +1198,8 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) * Return the value for field PAR if it's fixed in configuration space * defined by PARAMS. Return -EINVAL otherwise */ -static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var, int *dir) +int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir) { if (hw_is_mask(var)) { const snd_mask_t *mask = hw_param_mask_c(params, var); @@ -1301,7 +1296,6 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params, return changed; } -#if 0 /** * snd_pcm_hw_param_setinteger * @@ -1323,10 +1317,9 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm, } return 0; } -#endif /* 0 */ -static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var) +int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var) { int changed; if (hw_is_mask(var)) @@ -1352,9 +1345,9 @@ static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, * values > minimum. Reduce configuration space accordingly. * Return the minimum. */ -static int snd_pcm_hw_param_first(snd_pcm_t *pcm, - snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var, int *dir) +int snd_pcm_hw_param_first(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir) { int changed = _snd_pcm_hw_param_first(params, var); if (changed < 0) @@ -1366,8 +1359,8 @@ static int snd_pcm_hw_param_first(snd_pcm_t *pcm, return snd_pcm_hw_param_value(params, var, dir); } -static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var) +int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var) { int changed; if (hw_is_mask(var)) @@ -1393,9 +1386,9 @@ static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, * values < maximum. Reduce configuration space accordingly. * Return the maximum. */ -static int snd_pcm_hw_param_last(snd_pcm_t *pcm, - snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var, int *dir) +int snd_pcm_hw_param_last(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir) { int changed = _snd_pcm_hw_param_last(params, var); if (changed < 0) @@ -1444,9 +1437,8 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, * values < VAL. Reduce configuration space accordingly. * Return new minimum or -EINVAL if the configuration space is empty */ -static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var, unsigned int val, - int *dir) +int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, unsigned int val, int *dir) { int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); if (changed < 0) @@ -1459,9 +1451,8 @@ static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, return snd_pcm_hw_param_value_min(params, var, dir); } -static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) +int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, unsigned int val, int dir) { int changed; int open = 0; @@ -1499,9 +1490,8 @@ static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, * values >= VAL + 1. Reduce configuration space accordingly. * Return new maximum or -EINVAL if the configuration space is empty */ -static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - snd_pcm_hw_param_t var, unsigned int val, - int *dir) +int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, unsigned int val, int *dir) { int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); if (changed < 0) @@ -2574,6 +2564,9 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream, EXPORT_SYMBOL(snd_interval_refine); EXPORT_SYMBOL(snd_interval_list); EXPORT_SYMBOL(snd_interval_ratnum); +EXPORT_SYMBOL(snd_interval_muldivk); +EXPORT_SYMBOL(snd_interval_mulkdiv); +EXPORT_SYMBOL(snd_interval_div); EXPORT_SYMBOL(_snd_pcm_hw_params_any); EXPORT_SYMBOL(_snd_pcm_hw_param_min); EXPORT_SYMBOL(_snd_pcm_hw_param_set); @@ -2587,6 +2580,7 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last); EXPORT_SYMBOL(snd_pcm_hw_param_near); EXPORT_SYMBOL(snd_pcm_hw_param_set); EXPORT_SYMBOL(snd_pcm_hw_refine); +EXPORT_SYMBOL(snd_pcm_hw_params); EXPORT_SYMBOL(snd_pcm_hw_constraints_init); EXPORT_SYMBOL(snd_pcm_hw_constraints_complete); EXPORT_SYMBOL(snd_pcm_hw_constraint_list); diff --git a/trunk/sound/core/pcm_memory.c b/trunk/sound/core/pcm_memory.c index 9a174fb96565..f1d5f7a6ee0c 100644 --- a/trunk/sound/core/pcm_memory.c +++ b/trunk/sound/core/pcm_memory.c @@ -204,7 +204,6 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream, entry->c.text.read = snd_pcm_lib_preallocate_proc_read; entry->c.text.write_size = 64; entry->c.text.write = snd_pcm_lib_preallocate_proc_write; - entry->mode |= S_IWUSR; entry->private_data = substream; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/trunk/sound/core/pcm_misc.c b/trunk/sound/core/pcm_misc.c index 1453743e4da0..422b8db14154 100644 --- a/trunk/sound/core/pcm_misc.c +++ b/trunk/sound/core/pcm_misc.c @@ -269,6 +269,22 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format) return !val; } +/** + * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian + * @format: the format to check + * + * Returns 1 if the given PCM format is CPU-endian, 0 if + * opposite, or a negative error code if endian not specified. + */ +int snd_pcm_format_cpu_endian(snd_pcm_format_t format) +{ +#ifdef SNDRV_LITTLE_ENDIAN + return snd_pcm_format_little_endian(format); +#else + return snd_pcm_format_big_endian(format); +#endif +} + /** * snd_pcm_format_width - return the bit-width of the format * @format: the format to check diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index 10c2c9832649..cad9bbde9986 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -337,8 +337,8 @@ static int snd_pcm_hw_refine_user(snd_pcm_substream_t * substream, snd_pcm_hw_pa return err; } -static int snd_pcm_hw_params(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t *params) +int snd_pcm_hw_params(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *params) { snd_pcm_runtime_t *runtime; int err; @@ -1368,32 +1368,43 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; + down_read(&snd_pcm_link_rwsem); snd_power_lock(card); if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); - if (result < 0) { - snd_power_unlock(card); - return result; - } + if (result < 0) + goto _unlock; } /* allocate temporary record for drain sync */ - down_read(&snd_pcm_link_rwsem); if (snd_pcm_stream_linked(substream)) { drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); if (! drec) { - up_read(&snd_pcm_link_rwsem); - snd_power_unlock(card); - return -ENOMEM; + result = -ENOMEM; + goto _unlock; } } else drec = &drec_tmp; - /* count only playback streams */ + snd_pcm_stream_lock_irq(substream); + /* resume pause */ + if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) + snd_pcm_pause(substream, 0); + + /* pre-start/stop - all running streams are changed to DRAINING state */ + result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); + if (result < 0) + goto _end; + + /* check streams with PLAYBACK & DRAINING */ num_drecs = 0; snd_pcm_group_for_each(pos, substream) { snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos); runtime = s->runtime; + if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) { + runtime->status->state = SNDRV_PCM_STATE_SETUP; + continue; + } if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { d = &drec[num_drecs++]; d->substream = s; @@ -1407,21 +1418,9 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) runtime->stop_threshold = runtime->buffer_size; } } - up_read(&snd_pcm_link_rwsem); - if (! num_drecs) - goto _error; - snd_pcm_stream_lock_irq(substream); - /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) - snd_pcm_pause(substream, 0); - - /* pre-start/stop - all running streams are changed to DRAINING state */ - result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); - if (result < 0) { - snd_pcm_stream_unlock_irq(substream); - goto _error; - } + if (! num_drecs) + goto _end; for (;;) { long tout; @@ -1429,15 +1428,6 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) result = -ERESTARTSYS; break; } - /* all finished? */ - for (i = 0; i < num_drecs; i++) { - runtime = drec[i].substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) - break; - } - if (i == num_drecs) - break; /* yes, all drained */ - set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_unlock_irq(substream); snd_power_unlock(card); @@ -1454,11 +1444,15 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) } break; } + /* all finished? */ + for (i = 0; i < num_drecs; i++) { + runtime = drec[i].substream->runtime; + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) + break; + } + if (i == num_drecs) + break; } - - snd_pcm_stream_unlock_irq(substream); - - _error: for (i = 0; i < num_drecs; i++) { d = &drec[i]; runtime = d->substream->runtime; @@ -1466,9 +1460,13 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) runtime->stop_threshold = d->stop_threshold; } + _end: + snd_pcm_stream_unlock_irq(substream); if (drec != &drec_tmp) kfree(drec); + _unlock: snd_power_unlock(card); + up_read(&snd_pcm_link_rwsem); return result; } diff --git a/trunk/sound/core/seq/oss/seq_oss_synth.c b/trunk/sound/core/seq/oss/seq_oss_synth.c index 1a7736cbf3a4..638cc148706d 100644 --- a/trunk/sound/core/seq/oss/seq_oss_synth.c +++ b/trunk/sound/core/seq/oss/seq_oss_synth.c @@ -325,10 +325,14 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp) } snd_use_lock_free(&rec->use_lock); } - kfree(info->sysex); - info->sysex = NULL; - kfree(info->ch); - info->ch = NULL; + if (info->sysex) { + kfree(info->sysex); + info->sysex = NULL; + } + if (info->ch) { + kfree(info->ch); + info->ch = NULL; + } } dp->synth_opened = 0; dp->max_synthdev = 0; @@ -414,10 +418,14 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev) dp->file_mode) < 0) { midi_synth_dev.opened--; info->opened = 0; - kfree(info->sysex); - info->sysex = NULL; - kfree(info->ch); - info->ch = NULL; + if (info->sysex) { + kfree(info->sysex); + info->sysex = NULL; + } + if (info->ch) { + kfree(info->ch); + info->ch = NULL; + } } return; } diff --git a/trunk/sound/core/seq/seq_dummy.c b/trunk/sound/core/seq/seq_dummy.c index ea945a5d2a0b..e88967c5b93d 100644 --- a/trunk/sound/core/seq/seq_dummy.c +++ b/trunk/sound/core/seq/seq_dummy.c @@ -140,7 +140,10 @@ dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int static void dummy_free(void *private_data) { - kfree(private_data); + snd_seq_dummy_port_t *p; + + p = private_data; + kfree(p); } /* diff --git a/trunk/sound/core/seq/seq_midi.c b/trunk/sound/core/seq/seq_midi.c index 57be9155eb62..18247db45db6 100644 --- a/trunk/sound/core/seq/seq_midi.c +++ b/trunk/sound/core/seq/seq_midi.c @@ -414,8 +414,6 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) if (newclient) synths[card->number] = client; up(®ister_mutex); - kfree(info); - kfree(port); return 0; /* success */ __nomem: diff --git a/trunk/sound/core/seq/seq_midi_event.c b/trunk/sound/core/seq/seq_midi_event.c index df1e2bb39745..21e569062bc3 100644 --- a/trunk/sound/core/seq/seq_midi_event.c +++ b/trunk/sound/core/seq/seq_midi_event.c @@ -171,13 +171,11 @@ void snd_midi_event_reset_decode(snd_midi_event_t *dev) spin_unlock_irqrestore(&dev->lock, flags); } -#if 0 void snd_midi_event_init(snd_midi_event_t *dev) { snd_midi_event_reset_encode(dev); snd_midi_event_reset_decode(dev); } -#endif /* 0 */ void snd_midi_event_no_status(snd_midi_event_t *dev, int on) { @@ -187,7 +185,6 @@ void snd_midi_event_no_status(snd_midi_event_t *dev, int on) /* * resize buffer */ -#if 0 int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize) { unsigned char *new_buf, *old_buf; @@ -207,7 +204,6 @@ int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize) kfree(old_buf); return 0; } -#endif /* 0 */ /* * read bytes and encode to sequencer event if finished @@ -521,6 +517,8 @@ static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int coun EXPORT_SYMBOL(snd_midi_event_new); EXPORT_SYMBOL(snd_midi_event_free); +EXPORT_SYMBOL(snd_midi_event_resize_buffer); +EXPORT_SYMBOL(snd_midi_event_init); EXPORT_SYMBOL(snd_midi_event_reset_encode); EXPORT_SYMBOL(snd_midi_event_reset_decode); EXPORT_SYMBOL(snd_midi_event_no_status); diff --git a/trunk/sound/core/seq/seq_queue.c b/trunk/sound/core/seq/seq_queue.c index 98de2e711fde..3afc7cc0c9a7 100644 --- a/trunk/sound/core/seq/seq_queue.c +++ b/trunk/sound/core/seq/seq_queue.c @@ -672,8 +672,7 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, i * process a received queue-control event. * this function is exported for seq_sync.c. */ -static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, - 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: diff --git a/trunk/sound/core/seq/seq_queue.h b/trunk/sound/core/seq/seq_queue.h index ea3c54216ea8..b1bf5519fb3b 100644 --- a/trunk/sound/core/seq/seq_queue.h +++ b/trunk/sound/core/seq/seq_queue.h @@ -111,6 +111,7 @@ int snd_seq_queue_use(int queueid, int client, int use); 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 atomic, int hop); /* * 64bit division - for sync stuff.. diff --git a/trunk/sound/core/seq/seq_timer.c b/trunk/sound/core/seq/seq_timer.c index a7f76fc95280..753f1c0863cc 100644 --- a/trunk/sound/core/seq/seq_timer.c +++ b/trunk/sound/core/seq/seq_timer.c @@ -36,8 +36,7 @@ extern int seq_default_timer_resolution; #define SKEW_BASE 0x10000 /* 16bit shift */ -static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, - int tempo, int ppq, int nticks) +void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks) { if (tempo < 1000000) tick->resolution = (tempo * 1000) / ppq; diff --git a/trunk/sound/core/seq/seq_timer.h b/trunk/sound/core/seq/seq_timer.h index 287ed68591de..4c0872df8931 100644 --- a/trunk/sound/core/seq/seq_timer.h +++ b/trunk/sound/core/seq/seq_timer.h @@ -64,6 +64,8 @@ extern seq_timer_t *snd_seq_timer_new(void); /* delete timer (destructor) */ extern void snd_seq_timer_delete(seq_timer_t **tmr); +void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks); + /* */ static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution) { diff --git a/trunk/sound/core/seq/seq_virmidi.c b/trunk/sound/core/seq/seq_virmidi.c index a66484b5cf0e..6b4e630ace54 100644 --- a/trunk/sound/core/seq/seq_virmidi.c +++ b/trunk/sound/core/seq/seq_virmidi.c @@ -110,7 +110,7 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_ * handler of a remote port which is attached to the virmidi via * SNDRV_VIRMIDI_SEQ_ATTACH. */ -#if 0 +/* exported */ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev) { snd_virmidi_dev_t *rdev; @@ -118,7 +118,6 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev) rdev = rmidi->private_data; return snd_virmidi_dev_receive_event(rdev, ev); } -#endif /* 0 */ /* * event handler of virmidi port @@ -385,7 +384,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev) info->client = client; info->type = KERNEL_CLIENT; sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device); - snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info); + snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info); /* create a port */ memset(pinfo, 0, sizeof(*pinfo)); @@ -406,7 +405,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev) pcallbacks.unuse = snd_virmidi_unuse; pcallbacks.event_input = snd_virmidi_event_input; pinfo->kernel = &pcallbacks; - err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo); + err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo); if (err < 0) { snd_seq_delete_kernel_client(client); rdev->client = -1; @@ -549,3 +548,4 @@ module_init(alsa_virmidi_init) module_exit(alsa_virmidi_exit) EXPORT_SYMBOL(snd_virmidi_new); +EXPORT_SYMBOL(snd_virmidi_receive); diff --git a/trunk/sound/core/sound.c b/trunk/sound/core/sound.c index 0815fadeb3ec..33eaa5e5d284 100644 --- a/trunk/sound/core/sound.c +++ b/trunk/sound/core/sound.c @@ -431,6 +431,7 @@ EXPORT_SYMBOL(snd_card_pci_resume); EXPORT_SYMBOL(snd_device_new); EXPORT_SYMBOL(snd_device_register); EXPORT_SYMBOL(snd_device_free); +EXPORT_SYMBOL(snd_device_free_all); /* isadma.c */ #ifdef CONFIG_ISA EXPORT_SYMBOL(snd_dma_program); diff --git a/trunk/sound/core/timer.c b/trunk/sound/core/timer.c index b498e5482d77..fa762ca439be 100644 --- a/trunk/sound/core/timer.c +++ b/trunk/sound/core/timer.c @@ -69,7 +69,6 @@ typedef struct { struct timespec tstamp; /* trigger tstamp */ wait_queue_head_t qchange_sleep; struct fasync_struct *fasync; - struct semaphore tread_sem; } snd_timer_user_t; /* list of timers */ @@ -845,7 +844,7 @@ int snd_timer_dev_register(snd_device_t *dev) return 0; } -static int snd_timer_unregister(snd_timer_t *timer) +int snd_timer_unregister(snd_timer_t *timer) { struct list_head *p, *n; snd_timer_instance_t *ti; @@ -946,6 +945,11 @@ struct snd_timer_system_private { unsigned long correction; }; +unsigned int snd_timer_system_resolution(void) +{ + return 1000000000L / HZ; +} + static void snd_timer_s_function(unsigned long data) { snd_timer_t *timer = (snd_timer_t *)data; @@ -1204,7 +1208,6 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) return -ENOMEM; spin_lock_init(&tu->qlock); init_waitqueue_head(&tu->qchange_sleep); - init_MUTEX(&tu->tread_sem); tu->ticks = 1; tu->queue_size = 128; tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); @@ -1451,51 +1454,46 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * snd_timer_user_t *tu; snd_timer_select_t tselect; char str[32]; - int err = 0; + int err; tu = file->private_data; - down(&tu->tread_sem); - if (tu->timeri) { + if (tu->timeri) snd_timer_close(tu->timeri); - tu->timeri = NULL; - } - if (copy_from_user(&tselect, _tselect, sizeof(tselect))) { - err = -EFAULT; - goto __err; - } + if (copy_from_user(&tselect, _tselect, sizeof(tselect))) + return -EFAULT; sprintf(str, "application %i", current->pid); if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) - goto __err; + return err; - kfree(tu->queue); - tu->queue = NULL; - kfree(tu->tqueue); - tu->tqueue = NULL; + if (tu->queue) { + kfree(tu->queue); + tu->queue = NULL; + } + if (tu->tqueue) { + kfree(tu->tqueue); + tu->tqueue = NULL; + } if (tu->tread) { tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); - if (tu->tqueue == NULL) - err = -ENOMEM; + if (tu->tqueue == NULL) { + snd_timer_close(tu->timeri); + return -ENOMEM; + } } else { tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); - if (tu->queue == NULL) - err = -ENOMEM; + if (tu->queue == NULL) { + snd_timer_close(tu->timeri); + return -ENOMEM; + } } - if (err < 0) { - snd_timer_close(tu->timeri); - tu->timeri = NULL; - } else { - tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; - tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; - tu->timeri->ccallback = snd_timer_user_ccallback; - tu->timeri->callback_data = (void *)tu; - } - - __err: - up(&tu->tread_sem); - return err; + tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; + tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; + tu->timeri->ccallback = snd_timer_user_ccallback; + tu->timeri->callback_data = (void *)tu; + return 0; } static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) @@ -1671,23 +1669,6 @@ static int snd_timer_user_continue(struct file *file) return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; } -static int snd_timer_user_pause(struct file *file) -{ - int err; - snd_timer_user_t *tu; - - tu = file->private_data; - snd_assert(tu->timeri != NULL, return -ENXIO); - return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; -} - -enum { - SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), - SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), - SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22), - SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), -}; - static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_timer_user_t *tu; @@ -1704,17 +1685,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l { int xarg; - down(&tu->tread_sem); - if (tu->timeri) { /* too late */ - up(&tu->tread_sem); + if (tu->timeri) /* too late */ return -EBUSY; - } - if (get_user(xarg, p)) { - up(&tu->tread_sem); + if (get_user(xarg, p)) return -EFAULT; - } tu->tread = xarg ? 1 : 0; - up(&tu->tread_sem); return 0; } case SNDRV_TIMER_IOCTL_GINFO: @@ -1732,17 +1707,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l case SNDRV_TIMER_IOCTL_STATUS: return snd_timer_user_status(file, argp); case SNDRV_TIMER_IOCTL_START: - case SNDRV_TIMER_IOCTL_START_OLD: return snd_timer_user_start(file); case SNDRV_TIMER_IOCTL_STOP: - case SNDRV_TIMER_IOCTL_STOP_OLD: return snd_timer_user_stop(file); case SNDRV_TIMER_IOCTL_CONTINUE: - case SNDRV_TIMER_IOCTL_CONTINUE_OLD: return snd_timer_user_continue(file); - case SNDRV_TIMER_IOCTL_PAUSE: - case SNDRV_TIMER_IOCTL_PAUSE_OLD: - return snd_timer_user_pause(file); } return -ENOTTY; } @@ -1929,3 +1898,4 @@ EXPORT_SYMBOL(snd_timer_global_free); EXPORT_SYMBOL(snd_timer_global_register); EXPORT_SYMBOL(snd_timer_global_unregister); EXPORT_SYMBOL(snd_timer_interrupt); +EXPORT_SYMBOL(snd_timer_system_resolution); diff --git a/trunk/sound/core/timer_compat.c b/trunk/sound/core/timer_compat.c index 3de552dfe80f..9fbc3957a22d 100644 --- a/trunk/sound/core/timer_compat.c +++ b/trunk/sound/core/timer_compat.c @@ -106,13 +106,8 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns case SNDRV_TIMER_IOCTL_SELECT: case SNDRV_TIMER_IOCTL_PARAMS: case SNDRV_TIMER_IOCTL_START: - case SNDRV_TIMER_IOCTL_START_OLD: case SNDRV_TIMER_IOCTL_STOP: - case SNDRV_TIMER_IOCTL_STOP_OLD: case SNDRV_TIMER_IOCTL_CONTINUE: - case SNDRV_TIMER_IOCTL_CONTINUE_OLD: - case SNDRV_TIMER_IOCTL_PAUSE: - case SNDRV_TIMER_IOCTL_PAUSE_OLD: case SNDRV_TIMER_IOCTL_NEXT_DEVICE: return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); case SNDRV_TIMER_IOCTL_INFO32: diff --git a/trunk/sound/drivers/vx/vx_pcm.c b/trunk/sound/drivers/vx/vx_pcm.c index af381b15fe5c..98587176b327 100644 --- a/trunk/sound/drivers/vx/vx_pcm.c +++ b/trunk/sound/drivers/vx/vx_pcm.c @@ -1264,10 +1264,14 @@ static void snd_vx_pcm_free(snd_pcm_t *pcm) { vx_core_t *chip = pcm->private_data; chip->pcm[pcm->device] = NULL; - kfree(chip->playback_pipes); - chip->playback_pipes = NULL; - kfree(chip->capture_pipes); - chip->capture_pipes = NULL; + if (chip->playback_pipes) { + kfree(chip->playback_pipes); + chip->playback_pipes = NULL; + } + if (chip->capture_pipes) { + kfree(chip->capture_pipes); + chip->capture_pipes = NULL; + } } /* diff --git a/trunk/sound/i2c/tea6330t.c b/trunk/sound/i2c/tea6330t.c index 2da8d7f157f4..bb503e70b664 100644 --- a/trunk/sound/i2c/tea6330t.c +++ b/trunk/sound/i2c/tea6330t.c @@ -266,7 +266,8 @@ TEA6330T_TREBLE("Tone Control - Treble", 0) static void snd_tea6330_free(snd_i2c_device_t *device) { - kfree(device->private_data); + tea6330t_t *tea = device->private_data; + kfree(tea); } int snd_tea6330t_update_mixer(snd_card_t * card, diff --git a/trunk/sound/isa/Kconfig b/trunk/sound/isa/Kconfig index 148a856a43ad..3a3228b18726 100644 --- a/trunk/sound/isa/Kconfig +++ b/trunk/sound/isa/Kconfig @@ -179,7 +179,6 @@ config SND_INTERWAVE_STB select SND_RAWMIDI select SND_CS4231_LIB select SND_GUS_SYNTH - select ISAPNP help Say Y here to include support for AMD InterWave based soundcards with a TEA6330T bass and treble regulator diff --git a/trunk/sound/isa/ad1816a/ad1816a.c b/trunk/sound/isa/ad1816a/ad1816a.c index 563296d02894..9fa7a78da6c3 100644 --- a/trunk/sound/isa/ad1816a/ad1816a.c +++ b/trunk/sound/isa/ad1816a/ad1816a.c @@ -83,8 +83,6 @@ struct snd_card_ad1816a { static struct pnp_card_device_id snd_ad1816a_pnpids[] = { /* Analog Devices AD1815 */ { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, - /* Analog Device AD1816? */ - { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, /* Analog Devices AD1816A - added by Kenneth Platz */ { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */ diff --git a/trunk/sound/isa/cs423x/cs4236.c b/trunk/sound/isa/cs423x/cs4236.c index 39f4eff44f5c..e745a54e00a1 100644 --- a/trunk/sound/isa/cs423x/cs4236.c +++ b/trunk/sound/isa/cs423x/cs4236.c @@ -349,7 +349,8 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard, pnp_init_resource_table(cfg); if (mpu_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2); - if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0) + if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 && + pnp_irq_valid(pdev, 0)) pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1); err = pnp_manual_config_dev(pdev, cfg, 0); if (err < 0) diff --git a/trunk/sound/isa/gus/gus_io.c b/trunk/sound/isa/gus/gus_io.c index 337b0e2a8a36..f0570f2bf75f 100644 --- a/trunk/sound/isa/gus/gus_io.c +++ b/trunk/sound/isa/gus/gus_io.c @@ -244,8 +244,6 @@ unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg) return res; } -#if 0 - void snd_gf1_i_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data) @@ -267,8 +265,6 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, spin_unlock_irqrestore(&gus->reg_lock, flags); } -#endif /* 0 */ - unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit) { @@ -333,8 +329,6 @@ unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr) return res; } -#if 0 - void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data) { unsigned long flags; @@ -411,7 +405,9 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, spin_unlock_irqrestore(&gus->reg_lock, flags); } -#endif /* 0 */ +/* + + */ void snd_gf1_select_active_voices(snd_gus_card_t * gus) { @@ -473,8 +469,6 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus) printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); } -#if 0 - void snd_gf1_print_global_registers(snd_gus_card_t * gus) { unsigned char global_mode = 0x00; @@ -534,6 +528,4 @@ void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count } } -#endif /* 0 */ - #endif diff --git a/trunk/sound/isa/gus/gus_main.c b/trunk/sound/isa/gus/gus_main.c index 94bbd344be5e..73f81c14f768 100644 --- a/trunk/sound/isa/gus/gus_main.c +++ b/trunk/sound/isa/gus/gus_main.c @@ -459,6 +459,7 @@ EXPORT_SYMBOL(snd_gf1_write16); EXPORT_SYMBOL(snd_gf1_look16); EXPORT_SYMBOL(snd_gf1_i_write8); EXPORT_SYMBOL(snd_gf1_i_look8); +EXPORT_SYMBOL(snd_gf1_i_write16); EXPORT_SYMBOL(snd_gf1_i_look16); EXPORT_SYMBOL(snd_gf1_dram_addr); EXPORT_SYMBOL(snd_gf1_write_addr); @@ -469,6 +470,8 @@ EXPORT_SYMBOL(snd_gf1_alloc_voice); EXPORT_SYMBOL(snd_gf1_free_voice); EXPORT_SYMBOL(snd_gf1_ctrl_stop); EXPORT_SYMBOL(snd_gf1_stop_voice); +EXPORT_SYMBOL(snd_gf1_start); +EXPORT_SYMBOL(snd_gf1_stop); /* gus_mixer.c */ EXPORT_SYMBOL(snd_gf1_new_mixer); /* gus_pcm.c */ diff --git a/trunk/sound/isa/gus/gus_mem.c b/trunk/sound/isa/gus/gus_mem.c index 609838e8ef67..bfc2b91001d5 100644 --- a/trunk/sound/isa/gus/gus_mem.c +++ b/trunk/sound/isa/gus/gus_mem.c @@ -39,8 +39,8 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup) } } -static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc, - snd_gf1_mem_block_t * block) +snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc, + snd_gf1_mem_block_t * block) { snd_gf1_mem_block_t *pblock, *nblock; @@ -105,8 +105,8 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block) return 0; } -static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, - unsigned int address) +snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, + unsigned int address) { snd_gf1_mem_block_t *block; @@ -118,8 +118,8 @@ static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, return NULL; } -static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, - unsigned int *share_id) +snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, + unsigned int *share_id) { snd_gf1_mem_block_t *block; diff --git a/trunk/sound/isa/gus/gus_pcm.c b/trunk/sound/isa/gus/gus_pcm.c index b75066ab46fc..8995ad9c516d 100644 --- a/trunk/sound/isa/gus/gus_pcm.c +++ b/trunk/sound/isa/gus/gus_pcm.c @@ -656,7 +656,8 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture = static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime) { - kfree(runtime->private_data); + gus_pcm_private_t * pcmp = runtime->private_data; + kfree(pcmp); } static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream) diff --git a/trunk/sound/isa/gus/gus_reset.c b/trunk/sound/isa/gus/gus_reset.c index ef687abc7070..b4e66f6a10ae 100644 --- a/trunk/sound/isa/gus/gus_reset.c +++ b/trunk/sound/isa/gus/gus_reset.c @@ -161,8 +161,7 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice) #endif } -static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, - unsigned short v_max) +void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max) { unsigned long flags; unsigned int daddr; diff --git a/trunk/sound/isa/gus/gus_synth.c b/trunk/sound/isa/gus/gus_synth.c index f51c386ee192..66552e6013a4 100644 --- a/trunk/sound/isa/gus/gus_synth.c +++ b/trunk/sound/isa/gus/gus_synth.c @@ -99,8 +99,7 @@ static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0); } -static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, - void *private_data, int atomic, int hop) +int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop) { snd_gus_port_t * p = (snd_gus_port_t *) private_data; diff --git a/trunk/sound/isa/gus/gus_tables.h b/trunk/sound/isa/gus/gus_tables.h index 4adf098d3269..ed8e9d85ad31 100644 --- a/trunk/sound/isa/gus/gus_tables.h +++ b/trunk/sound/isa/gus/gus_tables.h @@ -23,8 +23,6 @@ #ifdef __GUS_TABLES_ALLOC__ -#if 0 - unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = { 8372, 8870, 9397, 9956, 10548, 11175, @@ -51,8 +49,6 @@ unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = 12123977, 12844906 }; -#endif /* 0 */ - unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = { 4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */, 1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */, diff --git a/trunk/sound/isa/gus/gus_volume.c b/trunk/sound/isa/gus/gus_volume.c index 3d36f6c8ee6a..b72bcfb28617 100644 --- a/trunk/sound/isa/gus/gus_volume.c +++ b/trunk/sound/isa/gus/gus_volume.c @@ -55,8 +55,6 @@ unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol) return (e << 8) | m; } -#if 0 - unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) { unsigned int rvol; @@ -110,8 +108,6 @@ unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus, return (range << 6) | (increment & 0x3f); } -#endif /* 0 */ - unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16) { freq16 >>= 3; @@ -124,8 +120,6 @@ unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16) return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; } -#if 0 - short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) { static short vibrato_table[] = @@ -214,5 +208,3 @@ unsigned short snd_gf1_compute_freq(unsigned int freq, } return (unsigned short) fc; } - -#endif /* 0 */ diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig index 6d7a00f34d82..428efdbd70a1 100644 --- a/trunk/sound/pci/Kconfig +++ b/trunk/sound/pci/Kconfig @@ -274,19 +274,6 @@ config SND_HDSP To compile this driver as a module, choose M here: the module will be called snd-hdsp. -config SND_HDSPM - tristate "RME Hammerfall DSP MADI" - depends on SND - select SND_HWDEP - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for RME Hammerfall DSP MADI - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-hdspm. - config SND_TRIDENT tristate "Trident 4D-Wave DX/NX; SiS 7018" depends on SND diff --git a/trunk/sound/pci/ac97/ac97_codec.c b/trunk/sound/pci/ac97/ac97_codec.c index a4b72cd2eea0..0b024ec1f709 100644 --- a/trunk/sound/pci/ac97/ac97_codec.c +++ b/trunk/sound/pci/ac97/ac97_codec.c @@ -120,7 +120,6 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL }, { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, -{ 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, { 0x434d4978, 0xffffffff, "CMI9761", patch_cm9761, NULL }, { 0x434d4982, 0xffffffff, "CMI9761", patch_cm9761, NULL }, { 0x434d4983, 0xffffffff, "CMI9761", patch_cm9761, NULL }, @@ -150,7 +149,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, { 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, -{ 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, +{ 0x53494c20, 0xffffffe0, "Si3036,8", NULL, mpatch_si3036 }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, { 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99] @@ -463,14 +462,12 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; - unsigned short val, bitmask; + unsigned short val; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) - ; val = snd_ac97_read_cache(ac97, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); + ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1); if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1); + ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1); return 0; } @@ -480,19 +477,17 @@ int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u ac97_t *ac97 = snd_kcontrol_chip(kcontrol); struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; unsigned short val; - unsigned short mask, bitmask; + unsigned short mask; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->mask - 1) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << e->shift_l; + mask = (e->mask - 1) << e->shift_l; if (e->shift_l != e->shift_r) { if (ucontrol->value.enumerated.item[1] > e->mask - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= (e->mask - 1) << e->shift_r; } return snd_ac97_update_bits(ac97, e->reg, mask, val); } @@ -663,14 +658,14 @@ AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1), AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1) }; +static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = { +AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), +AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), +}; + static const snd_kcontrol_new_t snd_ac97_control_eapd = AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1); -static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = { -AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0), -AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0) -}; - /* change the existing EAPD control as inverted */ static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl) { @@ -1077,9 +1072,9 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max unsigned short val; snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); val = snd_ac97_read(ac97, reg); - if (! *lo_max && (val & 0x7f) == cbit[i]) + if (! *lo_max && (val & cbit[i])) *lo_max = max[i]; - if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i]) + if (! *hi_max && (val & (cbit[i] << 8))) *hi_max = max[i]; if (*lo_max && *hi_max) break; @@ -1531,25 +1526,13 @@ static int snd_ac97_mixer_build(ac97_t * ac97) static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97) { - int err, idx; - + /* TODO */ //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG)); snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0); snd_ac97_write(ac97, AC97_MISC_AFE, 0x0); - - /* build modem switches */ - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++) - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0) - return err; - - /* build chip specific controls */ - if (ac97->build_ops->build_specific) - if ((err = ac97->build_ops->build_specific(ac97)) < 0) - return err; - return 0; } @@ -1889,11 +1872,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) goto __access_ok; } - /* reset to defaults */ - if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) - snd_ac97_write(ac97, AC97_RESET, 0); - if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) - snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); + snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */ if (bus->ops->wait) bus->ops->wait(ac97); else { @@ -1985,21 +1964,21 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) /* note: it's important to set the rate at first */ tmp = AC97_MEA_GPIO; if (ac97->ext_mid & AC97_MEI_LINE1) { - snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000); + snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000); tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1; } if (ac97->ext_mid & AC97_MEI_LINE2) { - snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000); + snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000); tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2; } if (ac97->ext_mid & AC97_MEI_HANDSET) { - snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000); + snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000); tmp |= AC97_MEA_HADC | AC97_MEA_HDAC; } - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); + snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8)); udelay(100); /* nothing should be in powerdown mode */ - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); + snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8)); end_time = jiffies + (HZ / 10); do { if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) @@ -2542,11 +2521,11 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o return result; } - for (; quirk->subvendor; quirk++) { - if (quirk->subvendor != ac97->subsystem_vendor) + for (; quirk->vendor; quirk++) { + if (quirk->vendor != ac97->subsystem_vendor) continue; - if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) || - quirk->subdevice == (quirk->mask & ac97->subsystem_device)) { + if ((! quirk->mask && quirk->device == ac97->subsystem_device) || + quirk->device == (quirk->mask & ac97->subsystem_device)) { if (quirk->codec_id && quirk->codec_id != ac97->id) continue; snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device); diff --git a/trunk/sound/pci/ac97/ac97_patch.c b/trunk/sound/pci/ac97/ac97_patch.c index a15eb8522b7c..13c34a5d8206 100644 --- a/trunk/sound/pci/ac97/ac97_patch.c +++ b/trunk/sound/pci/ac97/ac97_patch.c @@ -64,116 +64,6 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor return ret; } -/* - * shared line-in/mic controls - */ -static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo, - const char **texts, unsigned int nums) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = nums; - if (uinfo->value.enumerated.item > nums - 1) - uinfo->value.enumerated.item = nums - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - static const char *texts[] = { "Shared", "Independent" }; - return ac97_enum_text_info(kcontrol, uinfo, texts, 2); -} - -static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ac97->indep_surround; - return 0; -} - -static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - unsigned char indep = !!ucontrol->value.enumerated.item[0]; - - if (indep != ac97->indep_surround) { - ac97->indep_surround = indep; - if (ac97->build_ops->update_jacks) - ac97->build_ops->update_jacks(ac97); - return 1; - } - return 0; -} - -static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - static const char *texts[] = { "2ch", "4ch", "6ch" }; - if (kcontrol->private_value) - return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */ - return ac97_enum_text_info(kcontrol, uinfo, texts, 3); -} - -static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ac97->channel_mode; - return 0; -} - -static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - unsigned char mode = ucontrol->value.enumerated.item[0]; - - if (mode != ac97->channel_mode) { - ac97->channel_mode = mode; - if (ac97->build_ops->update_jacks) - ac97->build_ops->update_jacks(ac97); - return 1; - } - return 0; -} - -#define AC97_SURROUND_JACK_MODE_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Surround Jack Mode", \ - .info = ac97_surround_jack_mode_info, \ - .get = ac97_surround_jack_mode_get, \ - .put = ac97_surround_jack_mode_put, \ - } -#define AC97_CHANNEL_MODE_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Channel Mode", \ - .info = ac97_channel_mode_info, \ - .get = ac97_channel_mode_get, \ - .put = ac97_channel_mode_put, \ - } -#define AC97_CHANNEL_MODE_4CH_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Channel Mode", \ - .info = ac97_channel_mode_info, \ - .get = ac97_channel_mode_get, \ - .put = ac97_channel_mode_put, \ - .private_value = 1, \ - } - -static inline int is_shared_linein(ac97_t *ac97) -{ - return ! ac97->indep_surround && ac97->channel_mode >= 1; -} - -static inline int is_shared_micin(ac97_t *ac97) -{ - return ! ac97->indep_surround && ac97->channel_mode >= 2; -} - - /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */ @@ -1500,16 +1390,6 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val); } -static void ad1888_update_jacks(ac97_t *ac97) -{ - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, - is_shared_linein(ac97) ? 0 : 1 << 12); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, - is_shared_micin(ac97) ? 0 : 1 << 11); -} - static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1526,8 +1406,8 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { .get = snd_ac97_ad1888_downmix_get, .put = snd_ac97_ad1888_downmix_put }, - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, + AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0), + AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0), }; static int patch_ad1888_specific(ac97_t *ac97) @@ -1542,9 +1422,8 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, .build_specific = patch_ad1888_specific, #ifdef CONFIG_PM - .resume = ad18xx_resume, + .resume = ad18xx_resume #endif - .update_jacks = ad1888_update_jacks, }; int patch_ad1888(ac97_t * ac97) @@ -1580,9 +1459,8 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, .build_specific = patch_ad1980_specific, #ifdef CONFIG_PM - .resume = ad18xx_resume, + .resume = ad18xx_resume #endif - .update_jacks = ad1888_update_jacks, }; int patch_ad1980(ac97_t * ac97) @@ -1593,21 +1471,10 @@ int patch_ad1980(ac97_t * ac97) } static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = { + AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0), AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) }; -static void ad1985_update_jacks(ac97_t *ac97) -{ - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, - is_shared_linein(ac97) ? 0 : 1 << 12); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, - is_shared_micin(ac97) ? 0 : 1 << 11); - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9, - is_shared_micin(ac97) ? 0 : 1 << 9); -} - static int patch_ad1985_specific(ac97_t *ac97) { int err; @@ -1621,9 +1488,8 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, .build_specific = patch_ad1985_specific, #ifdef CONFIG_PM - .resume = ad18xx_resume, + .resume = ad18xx_resume #endif - .update_jacks = ad1985_update_jacks, }; int patch_ad1985(ac97_t * ac97) @@ -1655,25 +1521,31 @@ int patch_ad1985(ac97_t * ac97) /* * realtek ALC65x/850 codecs */ -static void alc650_update_jacks(ac97_t *ac97) +static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) { - int shared; - - /* shared Line-In */ - shared = is_shared_linein(ac97); - snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9, - shared ? (1 << 9) : 0); - /* update shared Mic */ - shared = is_shared_micin(ac97); - /* disable/enable vref */ - snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, - shared ? (1 << 12) : 0); - /* turn on/off center-on-mic */ - snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, - shared ? (1 << 10) : 0); - /* GPIO0 high for mic */ - snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, - shared ? 0 : 0x100); + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1; + return 0; +} + +static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int change, val; + val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10)); + change = (ucontrol->value.integer.value[0] != val); + if (change) { + /* disable/enable vref */ + snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, + ucontrol->value.integer.value[0] ? (1 << 12) : 0); + /* turn on/off center-on-mic */ + snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, + ucontrol->value.integer.value[0] ? (1 << 10) : 0); + /* GPIO0 high for mic */ + snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, + ucontrol->value.integer.value[0] ? 0 : 0x100); + } + return change; } static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { @@ -1686,8 +1558,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { /* 6: Independent Master Volume Right */ /* 7: Independent Master Volume Left */ /* 8: reserved */ - /* 9: Line-In/Surround share */ - /* 10: Mic/CLFE share */ + AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0), + /* 10: mic, see below */ /* 11-13: in IEC958 controls */ AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), #if 0 /* always set in patch_alc650 */ @@ -1698,8 +1570,14 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1), AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1), #endif - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic As Center/LFE", + .info = snd_ac97_info_volsw, + .get = snd_ac97_alc650_mic_get, + .put = snd_ac97_alc650_mic_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, }; static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = { @@ -1723,8 +1601,7 @@ static int patch_alc650_specific(ac97_t * ac97) } static struct snd_ac97_build_ops patch_alc650_ops = { - .build_specific = patch_alc650_specific, - .update_jacks = alc650_update_jacks + .build_specific = patch_alc650_specific }; int patch_alc650(ac97_t * ac97) @@ -1782,27 +1659,37 @@ int patch_alc650(ac97_t * ac97) return 0; } -static void alc655_update_jacks(ac97_t *ac97) +static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) { - int shared; - - /* shared Line-In */ - shared = is_shared_linein(ac97); - ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9, - shared ? (1 << 9) : 0, 0); - /* update shared mic */ - shared = is_shared_micin(ac97); + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1; + return 0; +} + +static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + /* misc control; vrefout disable */ snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, - shared ? (1 << 12) : 0); - ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, - shared ? (1 << 10) : 0, 0); + ucontrol->value.integer.value[0] ? (1 << 12) : 0); + return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, + ucontrol->value.integer.value[0] ? (1 << 10) : 0, + 0); } + static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, + AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic As Center/LFE", + .info = snd_ac97_info_volsw, + .get = snd_ac97_alc655_mic_get, + .put = snd_ac97_alc655_mic_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, }; static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -1872,8 +1759,7 @@ static int patch_alc655_specific(ac97_t * ac97) } static struct snd_ac97_build_ops patch_alc655_ops = { - .build_specific = patch_alc655_specific, - .update_jacks = alc655_update_jacks + .build_specific = patch_alc655_specific }; int patch_alc655(ac97_t * ac97) @@ -1912,33 +1798,63 @@ int patch_alc655(ac97_t * ac97) #define AC97_ALC850_JACK_SELECT 0x76 #define AC97_ALC850_MISC1 0x7a -static void alc850_update_jacks(ac97_t *ac97) +static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) { - int shared; - - /* shared Line-In */ - shared = is_shared_linein(ac97); + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2; + return 0; +} + +static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + /* SURR 1kOhm (bit4), Amp (bit5) */ snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), - shared ? (1<<5) : (1<<4)); + ucontrol->value.integer.value[0] ? (1<<5) : (1<<4)); /* LINE-IN = 0, SURROUND = 2 */ - snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, - shared ? (2<<12) : (0<<12)); - /* update shared mic */ - shared = is_shared_micin(ac97); + return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, + ucontrol->value.integer.value[0] ? (2<<12) : (0<<12)); +} + +static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2; + return 0; +} + +static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + /* Vref disable (bit12), 1kOhm (bit13) */ snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), - shared ? (1<<12) : (1<<13)); + ucontrol->value.integer.value[0] ? (1<<12) : (1<<13)); /* MIC-IN = 1, CENTER-LFE = 2 */ - snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, - shared ? (2<<4) : (1<<4)); + return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, + ucontrol->value.integer.value[0] ? (2<<4) : (1<<4)); } static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), - AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1), - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-In As Surround", + .info = snd_ac97_info_volsw, + .get = ac97_alc850_surround_get, + .put = ac97_alc850_surround_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic As Center/LFE", + .info = snd_ac97_info_volsw, + .get = ac97_alc850_mic_get, + .put = ac97_alc850_mic_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, + }; static int patch_alc850_specific(ac97_t *ac97) @@ -1955,8 +1871,7 @@ static int patch_alc850_specific(ac97_t *ac97) } static struct snd_ac97_build_ops patch_alc850_ops = { - .build_specific = patch_alc850_specific, - .update_jacks = alc850_update_jacks + .build_specific = patch_alc850_specific }; int patch_alc850(ac97_t *ac97) @@ -1996,17 +1911,9 @@ int patch_alc850(ac97_t *ac97) /* * C-Media CM97xx codecs */ -static void cm9738_update_jacks(ac97_t *ac97) -{ - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10, - is_shared_linein(ac97) ? (1 << 10) : 0); -} - static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = { + AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0), AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0), - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_4CH_CTL, }; static int patch_cm9738_specific(ac97_t * ac97) @@ -2015,8 +1922,7 @@ static int patch_cm9738_specific(ac97_t * ac97) } static struct snd_ac97_build_ops patch_cm9738_ops = { - .build_specific = patch_cm9738_specific, - .update_jacks = cm9738_update_jacks + .build_specific = patch_cm9738_specific }; int patch_cm9738(ac97_t * ac97) @@ -2080,19 +1986,34 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = { /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */ }; -static void cm9739_update_jacks(ac97_t *ac97) +static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + return 0; +} + +static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10, - is_shared_linein(ac97) ? (1 << 10) : 0); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, - is_shared_micin(ac97) ? 0x1000 : 0x2000); + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, + ucontrol->value.integer.value[0] ? + 0x1000 : 0x2000); } static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, + AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic As Center/LFE", + .info = snd_ac97_info_volsw, + .get = snd_ac97_cm9739_center_mic_get, + .put = snd_ac97_cm9739_center_mic_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, }; static int patch_cm9739_specific(ac97_t * ac97) @@ -2107,8 +2028,7 @@ static int patch_cm9739_post_spdif(ac97_t * ac97) static struct snd_ac97_build_ops patch_cm9739_ops = { .build_specific = patch_cm9739_specific, - .build_post_spdif = patch_cm9739_post_spdif, - .update_jacks = cm9739_update_jacks + .build_post_spdif = patch_cm9739_post_spdif }; int patch_cm9739(ac97_t * ac97) @@ -2167,97 +2087,71 @@ int patch_cm9739(ac97_t * ac97) } #define AC97_CM9761_MULTI_CHAN 0x64 -#define AC97_CM9761_FUNC 0x66 #define AC97_CM9761_SPDIF_CTRL 0x6c -static void cm9761_update_jacks(ac97_t *ac97) +static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - unsigned short surr_vals[2][2] = { - { 0x0008, 0x0400 }, /* off, on */ - { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ - }; - unsigned short clfe_vals[2][2] = { - { 0x2000, 0x1880 }, /* off, on */ - { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ - }; - - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408, - surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880, - clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]); + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + return 0; } -static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, -}; - -static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + unsigned short vals[2][2] = { + { 0x0008, 0x0400 }, /* off, on */ + { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ + }; + return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408, + vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]); } -static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - - if (ac97->regs[AC97_CM9761_FUNC] & 0x1) - ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */ - else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2) - ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */ + if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000) + ucontrol->value.integer.value[0] = 1; else - ucontrol->value.enumerated.item[0] = 0; /* AC-link */ + ucontrol->value.integer.value[0] = 0; + if (ac97->spec.dev_flags) /* 9761-82 rev.B */ + ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0]; return 0; } -static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.enumerated.item[0] == 2) - return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1); - snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0); - return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2, - ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0); + unsigned short vals[2][2] = { + { 0x2000, 0x1880 }, /* off, on */ + { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ + }; + return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880, + vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]); } -static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" }; -static const struct ac97_enum cm9761_dac_clock_enum = - AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock); - -static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = { - { /* BIT 1: SPDIFS */ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = cm9761_spdif_out_source_info, - .get = cm9761_spdif_out_source_get, - .put = cm9761_spdif_out_source_put, +static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-In As Surround", + .info = snd_ac97_info_volsw, + .get = snd_ac97_cm9761_linein_rear_get, + .put = snd_ac97_cm9761_linein_rear_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic As Center/LFE", + .info = snd_ac97_info_volsw, + .get = snd_ac97_cm9761_center_mic_get, + .put = snd_ac97_cm9761_center_mic_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ }, - /* BIT 2: IG_SPIV */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0), - /* BIT 3: SPI2F */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), - /* BIT 4: SPI2SDI */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0), - /* BIT 9-10: DAC_CTL */ - AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum), }; -static int patch_cm9761_post_spdif(ac97_t * ac97) -{ - return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif)); -} - static int patch_cm9761_specific(ac97_t * ac97) { return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls)); @@ -2265,8 +2159,7 @@ static int patch_cm9761_specific(ac97_t * ac97) static struct snd_ac97_build_ops patch_cm9761_ops = { .build_specific = patch_cm9761_specific, - .build_post_spdif = patch_cm9761_post_spdif, - .update_jacks = cm9761_update_jacks + .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */ }; int patch_cm9761(ac97_t *ac97) @@ -2300,25 +2193,24 @@ int patch_cm9761(ac97_t *ac97) /* to be sure: we overwrite the ext status bits */ snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); /* Don't set 0x0200 here. This results in the silent analog output */ - snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */ + 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 */ /* bit 15: pc master beep off - * bit 14: pin47 = EAPD/SPDIF + * bit 14: ?? * bit 13: vref ctl [= cm9739] - * bit 12: CLFE control (reverted on rev B) - * bit 11: Mic/center share (reverted on rev B) - * bit 10: suddound/line share - * bit 9: Analog-in mix -> surround - * bit 8: Analog-in mix -> CLFE - * bit 7: Mic/LFE share (mic/center/lfe) - * bit 5: vref select (9761A) - * bit 4: front control - * bit 3: surround control (revereted with rev B) - * bit 2: front mic - * bit 1: stereo mic - * bit 0: mic boost level (0=20dB, 1=30dB) + * bit 12: center/mic [= cm9739] (reverted on rev B) + * bit 11: ?? (mic/center/lfe) (reverted on rev B) + * bit 10: suddound/line [= cm9739] + * bit 9: mix 2 surround + * bit 8: ? + * bit 7: ?? (mic/center/lfe) + * bit 4: ?? (front) + * bit 3: ?? (line-in/rear share) (revereted with rev B) + * bit 2: ?? (surround) + * bit 1: front mic + * bit 0: mic boost */ #if 0 @@ -2338,47 +2230,6 @@ int patch_cm9761(ac97_t *ac97) return 0; } -#define AC97_CM9780_SIDE 0x60 -#define AC97_CM9780_JACK 0x62 -#define AC97_CM9780_MIXER 0x64 -#define AC97_CM9780_MULTI_CHAN 0x66 -#define AC97_CM9780_SPDIF 0x6c - -static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" }; -static const struct ac97_enum cm9780_ch_select_enum = - AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select); -static const snd_kcontrol_new_t cm9780_controls[] = { - AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1), - AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0), - AC97_ENUM("Side Playback Route", cm9780_ch_select_enum), -}; - -static int patch_cm9780_specific(ac97_t *ac97) -{ - return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls)); -} - -static struct snd_ac97_build_ops patch_cm9780_ops = { - .build_specific = patch_cm9780_specific, - .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */ -}; - -int patch_cm9780(ac97_t *ac97) -{ - unsigned short val; - - ac97->build_ops = &patch_cm9780_ops; - - /* enable spdif */ - if (ac97->ext_id & AC97_EI_SPDIF) { - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ - val = snd_ac97_read(ac97, AC97_CM9780_SPDIF); - val |= 0x1; /* SPDI_EN */ - snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val); - } - - return 0; -} /* * VIA VT1616 codec @@ -2412,21 +2263,9 @@ int patch_vt1616(ac97_t * ac97) return 0; } -/* - */ -static void it2646_update_jacks(ac97_t *ac97) -{ - /* shared Line-In */ - snd_ac97_update_bits(ac97, 0x76, 1 << 9, - is_shared_linein(ac97) ? (1<<9) : 0); - /* shared Mic */ - snd_ac97_update_bits(ac97, 0x76, 1 << 10, - is_shared_micin(ac97) ? (1<<10) : 0); -} - static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = { - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, + AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0), + AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0), }; static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = { @@ -2446,8 +2285,7 @@ static int patch_it2646_specific(ac97_t * ac97) } static struct snd_ac97_build_ops patch_it2646_ops = { - .build_specific = patch_it2646_specific, - .update_jacks = it2646_update_jacks + .build_specific = patch_it2646_specific }; int patch_it2646(ac97_t * ac97) @@ -2459,29 +2297,12 @@ int patch_it2646(ac97_t * ac97) return 0; } -/* - * Si3036 codec - */ - +/* Si3036/8 specific registers */ #define AC97_SI3036_CHIP_ID 0x5a -#define AC97_SI3036_LINE_CFG 0x5c - -static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = { -AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1) -}; - -static int patch_si3036_specific(ac97_t * ac97) -{ - return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036)); -} - -static struct snd_ac97_build_ops patch_si3036_ops = { - .build_specific = patch_si3036_specific, -}; int mpatch_si3036(ac97_t * ac97) { - ac97->build_ops = &patch_si3036_ops; + //printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a)); snd_ac97_write_cache(ac97, 0x5c, 0xf210 ); snd_ac97_write_cache(ac97, 0x68, 0); return 0; diff --git a/trunk/sound/pci/ac97/ac97_patch.h b/trunk/sound/pci/ac97/ac97_patch.h index 7b7377d0f2ae..6db51c96f5d0 100644 --- a/trunk/sound/pci/ac97/ac97_patch.h +++ b/trunk/sound/pci/ac97/ac97_patch.h @@ -54,7 +54,6 @@ int patch_alc850(ac97_t * ac97); int patch_cm9738(ac97_t * ac97); int patch_cm9739(ac97_t * ac97); int patch_cm9761(ac97_t * ac97); -int patch_cm9780(ac97_t * ac97); int patch_vt1616(ac97_t * ac97); int patch_it2646(ac97_t * ac97); int mpatch_si3036(ac97_t * ac97); diff --git a/trunk/sound/pci/ali5451/ali5451.c b/trunk/sound/pci/ali5451/ali5451.c index eb5c36d31a52..984d5d4ba4e1 100644 --- a/trunk/sound/pci/ali5451/ali5451.c +++ b/trunk/sound/pci/ali5451/ali5451.c @@ -98,8 +98,6 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); #define ALI_LEF_CHANNEL 23 #define ALI_SURR_LEFT_CHANNEL 26 #define ALI_SURR_RIGHT_CHANNEL 25 -#define ALI_MODEM_IN_CHANNEL 21 -#define ALI_MODEM_OUT_CHANNEL 20 #define SNDRV_ALI_VOICE_TYPE_PCM 01 #define SNDRV_ALI_VOICE_TYPE_OTH 02 @@ -124,15 +122,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); #define ALI_SCTRL 0x48 #define ALI_SPDIF_OUT_ENABLE 0x20 -#define ALI_SCTRL_LINE_IN2 (1 << 9) -#define ALI_SCTRL_GPIO_IN2 (1 << 13) -#define ALI_SCTRL_LINE_OUT_EN (1 << 20) -#define ALI_SCTRL_GPIO_OUT_EN (1 << 23) -#define ALI_SCTRL_CODEC1_READY (1 << 24) -#define ALI_SCTRL_CODEC2_READY (1 << 25) #define ALI_AC97_GPIO 0x4c -#define ALI_AC97_GPIO_ENABLE 0x8000 -#define ALI_AC97_GPIO_DATA_SHIFT 16 #define ALI_SPDIF_CS 0x70 #define ALI_SPDIF_CTRL 0x74 #define ALI_SPDIF_IN_FUNC_ENABLE 0x02 @@ -153,7 +143,6 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); #define TARGET_REACHED 0x00008000 #define MIXER_OVERFLOW 0x00000800 #define MIXER_UNDERFLOW 0x00000400 - #define GPIO_IRQ 0x01000000 #define ALI_SBBL_SBCL 0xc0 #define ALI_SBCTRL_SBE2R_SBDD 0xc4 #define ALI_STIMER 0xc8 @@ -173,9 +162,6 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); #define ALI_REG(codec, x) ((codec)->port + x) -#define MAX_CODECS 2 - - typedef struct snd_stru_ali ali_t; typedef struct snd_ali_stru_voice snd_ali_voice_t; @@ -259,7 +245,7 @@ struct snd_stru_ali { struct pci_dev *pci_m7101; snd_card_t *card; - snd_pcm_t *pcm[MAX_CODECS]; + snd_pcm_t *pcm; alidev_t synth; snd_ali_channel_control_t chregs; @@ -269,10 +255,8 @@ struct snd_stru_ali { unsigned int spurious_irq_count; unsigned int spurious_irq_max_delta; - unsigned int num_of_codecs; - ac97_bus_t *ac97_bus; - ac97_t *ac97[MAX_CODECS]; + ac97_t *ac97; unsigned short ac97_ext_id; unsigned short ac97_ext_status; @@ -505,12 +489,7 @@ static void snd_ali_codec_write(ac97_t *ac97, ali_t *codec = ac97->private_data; snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val); - if(reg == AC97_GPIO_STATUS) { - outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE, - ALI_REG(codec, ALI_AC97_GPIO)); - return; - } - snd_ali_codec_poke(codec, ac97->num, reg, val); + snd_ali_codec_poke(codec, 0, reg, val); return ; } @@ -520,7 +499,7 @@ static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg) ali_t *codec = ac97->private_data; snd_ali_printk("codec_read reg=%xh.\n", reg); - return (snd_ali_codec_peek(codec, ac97->num, reg)); + return (snd_ali_codec_peek(codec, 0, reg)); } /* @@ -1072,7 +1051,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq, } -static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel) +static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec) { snd_ali_voice_t *pvoice = NULL; unsigned long flags; @@ -1082,8 +1061,7 @@ static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, in spin_lock_irqsave(&codec->voice_alloc, flags); if (type == SNDRV_ALI_VOICE_TYPE_PCM) { - idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : - snd_ali_find_free_channel(codec,rec); + idx = snd_ali_find_free_channel(codec,rec); if(idx < 0) { snd_printk("ali_alloc_voice: err.\n"); spin_unlock_irqrestore(&codec->voice_alloc, flags); @@ -1319,7 +1297,7 @@ static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream, if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) { if (evoice == NULL) { - evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1); + evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0); if (evoice == NULL) return -ENOMEM; pvoice->extra = evoice; @@ -1350,13 +1328,13 @@ static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream) return 0; } -static int snd_ali_hw_params(snd_pcm_substream_t * substream, +static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } -static int snd_ali_hw_free(snd_pcm_substream_t * substream) +static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream) { return snd_pcm_lib_free_pages(substream); } @@ -1450,7 +1428,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream) } -static int snd_ali_prepare(snd_pcm_substream_t * substream) +static int snd_ali_capture_prepare(snd_pcm_substream_t * substream) { ali_t *codec = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -1468,13 +1446,11 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream) spin_lock_irqsave(&codec->reg_lock, flags); - snd_ali_printk("ali_prepare...\n"); + snd_ali_printk("capture_prepare...\n"); snd_ali_enable_special_channel(codec,pvoice->number); - Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL || - pvoice->number == ALI_MODEM_OUT_CHANNEL) ? - 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode); + Delta = snd_ali_convert_rate(runtime->rate, 1); // Prepare capture intr channel if (pvoice->number == ALI_SPDIF_IN_CHANNEL) { @@ -1558,7 +1534,7 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream } -static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream) { ali_t *codec = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -1640,8 +1616,7 @@ static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime) } } -static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel, - snd_pcm_hardware_t *phw) +static int snd_ali_playback_open(snd_pcm_substream_t * substream) { ali_t *codec = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -1649,7 +1624,7 @@ static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel, unsigned long flags = 0; spin_lock_irqsave(&codec->reg_lock, flags); - pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel); + pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0); if (pvoice == NULL) { spin_unlock_irqrestore(&codec->reg_lock, flags); return -EAGAIN; @@ -1661,31 +1636,49 @@ static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel, runtime->private_data = pvoice; runtime->private_free = snd_ali_pcm_free_substream; - runtime->hw = *phw; + runtime->hw = snd_ali_playback; snd_pcm_set_sync(substream); snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); return 0; } -static int snd_ali_playback_open(snd_pcm_substream_t * substream) -{ - return snd_ali_open(substream, 0, -1, &snd_ali_playback); -} static int snd_ali_capture_open(snd_pcm_substream_t * substream) { - return snd_ali_open(substream, 1, -1, &snd_ali_capture); + ali_t *codec = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + snd_ali_voice_t *pvoice; + unsigned long flags; + + spin_lock_irqsave(&codec->reg_lock, flags); + pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1); + if (pvoice == NULL) { + spin_unlock_irqrestore(&codec->reg_lock, flags); + return -EAGAIN; + } + pvoice->codec = codec; + spin_unlock_irqrestore(&codec->reg_lock, flags); + + pvoice->substream = substream; + runtime->private_data = pvoice; + runtime->private_free = snd_ali_pcm_free_substream; + runtime->hw = snd_ali_capture; + snd_pcm_set_sync(substream); + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); + return 0; } + static int snd_ali_playback_close(snd_pcm_substream_t * substream) { return 0; } -static int snd_ali_close(snd_pcm_substream_t * substream) +static int snd_ali_capture_close(snd_pcm_substream_t * substream) { ali_t *codec = snd_pcm_substream_chip(substream); - snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data; + snd_pcm_runtime_t *runtime = substream->runtime; + snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data; snd_ali_disable_special_channel(codec,pvoice->number); @@ -1705,121 +1698,29 @@ static snd_pcm_ops_t snd_ali_playback_ops = { static snd_pcm_ops_t snd_ali_capture_ops = { .open = snd_ali_capture_open, - .close = snd_ali_close, + .close = snd_ali_capture_close, .ioctl = snd_ali_ioctl, - .hw_params = snd_ali_hw_params, - .hw_free = snd_ali_hw_free, - .prepare = snd_ali_prepare, - .trigger = snd_ali_trigger, - .pointer = snd_ali_pointer, -}; - -/* - * Modem PCM - */ - -static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) -{ - ali_t *chip = snd_pcm_substream_chip(substream); - unsigned int modem_num = chip->num_of_codecs - 1; - snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params)); - snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0); - return snd_ali_hw_params(substream, hw_params); -} - -static snd_pcm_hardware_t snd_ali_modem = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000, - .rate_min = 8000, - .rate_max = 16000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = (256*1024), - .period_bytes_min = 64, - .period_bytes_max = (256*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel) -{ - static unsigned int rates [] = {8000,9600,12000,16000}; - static snd_pcm_hw_constraint_list_t hw_constraint_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - int err = snd_ali_open(substream, rec, channel, &snd_ali_modem); - if (err) - return err; - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates); -} - -static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream) -{ - return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL); -} - -static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream) -{ - return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL); -} - -static snd_pcm_ops_t snd_ali_modem_playback_ops = { - .open = snd_ali_modem_playback_open, - .close = snd_ali_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ali_modem_hw_params, - .hw_free = snd_ali_hw_free, - .prepare = snd_ali_prepare, - .trigger = snd_ali_trigger, - .pointer = snd_ali_pointer, -}; - -static snd_pcm_ops_t snd_ali_modem_capture_ops = { - .open = snd_ali_modem_capture_open, - .close = snd_ali_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ali_modem_hw_params, - .hw_free = snd_ali_hw_free, - .prepare = snd_ali_prepare, + .hw_params = snd_ali_capture_hw_params, + .hw_free = snd_ali_capture_hw_free, + .prepare = snd_ali_capture_prepare, .trigger = snd_ali_trigger, - .pointer = snd_ali_pointer, -}; - - -struct ali_pcm_description { - char *name; - unsigned int playback_num; - unsigned int capture_num; - snd_pcm_ops_t *playback_ops; - snd_pcm_ops_t *capture_ops; + .pointer = snd_ali_capture_pointer, }; static void snd_ali_pcm_free(snd_pcm_t *pcm) { ali_t *codec = pcm->private_data; - codec->pcm[pcm->device] = NULL; + codec->pcm = NULL; } - -static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc) +static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm) { snd_pcm_t *pcm; int err; - err = snd_pcm_new(codec->card, desc->name, device, - desc->playback_num, desc->capture_num, &pcm); + if (rpcm) *rpcm = NULL; + err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm); if (err < 0) { snd_printk("snd_ali_pcm: err called snd_pcm_new.\n"); return err; @@ -1827,36 +1728,20 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr pcm->private_data = codec; pcm->private_free = snd_ali_pcm_free; pcm->info_flags = 0; - if (desc->playback_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops); - if (desc->capture_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(codec->pci), 64*1024, 128*1024); pcm->info_flags = 0; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, desc->name); - codec->pcm[0] = pcm; + strcpy(pcm->name, "ALI 5451"); + codec->pcm = pcm; + if (rpcm) *rpcm = pcm; return 0; } -struct ali_pcm_description ali_pcms[] = { - { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops }, - { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops } -}; - -static int __devinit snd_ali_build_pcms(ali_t *codec) -{ - int i, err; - for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++) - if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0) - return err; - return 0; -} - - #define ALI5451_SPDIF(xname, xindex, value) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ @@ -1975,14 +1860,14 @@ static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus) static void snd_ali_mixer_free_ac97(ac97_t *ac97) { ali_t *codec = ac97->private_data; - codec->ac97[ac97->num] = NULL; + codec->ac97 = NULL; } static int __devinit snd_ali_mixer(ali_t * codec) { ac97_template_t ac97; unsigned int idx; - int i, err; + int err; static ac97_bus_ops_t ops = { .write = snd_ali_codec_write, .read = snd_ali_codec_read, @@ -1995,16 +1880,10 @@ static int __devinit snd_ali_mixer(ali_t * codec) memset(&ac97, 0, sizeof(ac97)); ac97.private_data = codec; ac97.private_free = snd_ali_mixer_free_ac97; - - for ( i = 0 ; i < codec->num_of_codecs ; i++) { - ac97.num = i; - if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) { - snd_printk("ali mixer %d creating error.\n", i); - if(i == 0) + if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97)) < 0) { + snd_printk("ali mixer creating error.\n"); return err; } - } - if (codec->spdif_support) { for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) { err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec)); @@ -2025,12 +1904,8 @@ static int ali_suspend(snd_card_t *card, pm_message_t state) if (! im) return 0; - for(i = 0 ; i < chip->num_of_codecs ; i++) { - if (chip->pcm[i]) - snd_pcm_suspend_all(chip->pcm[i]); - if(chip->ac97[i]) - snd_ac97_suspend(chip->ac97[i]); - } + snd_pcm_suspend_all(chip->pcm); + snd_ac97_suspend(chip->ac97); spin_lock_irq(&chip->reg_lock); @@ -2094,9 +1969,7 @@ static int ali_resume(snd_card_t *card) spin_unlock_irq(&chip->reg_lock); - for(i = 0 ; i < chip->num_of_codecs ; i++) - if(chip->ac97[i]) - snd_ac97_resume(chip->ac97[i]); + snd_ac97_resume(chip->ac97); return 0; } @@ -2163,37 +2036,11 @@ static int snd_ali_chip_init(ali_t *codec) codec->spdif_mask = 0x00000002; } - codec->num_of_codecs = 1; - - /* secondary codec - modem */ - if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) { - codec->num_of_codecs++; - outl(inl(ALI_REG(codec, ALI_SCTRL)) | - (ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN), - ALI_REG(codec, ALI_SCTRL)); - } - snd_ali_printk("chip initialize succeed.\n"); return 0; } -/* proc for register dump */ -static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf) -{ - ali_t *codec = entry->private_data; - int i; - for(i = 0 ; i < 256 ; i+= 4) - snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i))); -} - -static void __devinit snd_ali_proc_init(ali_t *codec) -{ - snd_info_entry_t *entry; - if(!snd_card_proc_new(codec->card, "ali5451", &entry)) - snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read); -} - static int __devinit snd_ali_resources(ali_t *codec) { int err; @@ -2386,13 +2233,11 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, } snd_ali_printk("pcm building ...\n"); - if ((err = snd_ali_build_pcms(codec)) < 0) { + if ((err = snd_ali_pcm(codec, 0, NULL)) < 0) { snd_card_free(card); return err; } - snd_ali_proc_init(codec); - strcpy(card->driver, "ALI5451"); strcpy(card->shortname, "ALI 5451"); @@ -2425,7 +2270,7 @@ static struct pci_driver driver = { static int __init alsa_card_ali_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_ali_exit(void) diff --git a/trunk/sound/pci/als4000.c b/trunk/sound/pci/als4000.c index ca28b229c704..f1a5f5723ee6 100644 --- a/trunk/sound/pci/als4000.c +++ b/trunk/sound/pci/als4000.c @@ -367,7 +367,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs * if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */ snd_pcm_period_elapsed(chip->capture_substream); if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */ - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); + snd_mpu401_uart_interrupt(irq, chip->rmidi, regs); /* release the gcr */ outb(gcr_status, chip->alt_port + 0xe); @@ -777,7 +777,7 @@ static struct pci_driver driver = { static int __init alsa_card_als4000_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_als4000_exit(void) diff --git a/trunk/sound/pci/atiixp.c b/trunk/sound/pci/atiixp.c index cafab4af5c57..6b04c0acc6f7 100644 --- a/trunk/sound/pci/atiixp.c +++ b/trunk/sound/pci/atiixp.c @@ -1334,8 +1334,8 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r static struct ac97_quirk ac97_quirks[] __devinitdata = { { - .subvendor = 0x103c, - .subdevice = 0x006b, + .vendor = 0x103c, + .device = 0x006b, .name = "HP Pavilion ZV5030US", .type = AC97_TUNE_MUTE_LED }, @@ -1645,7 +1645,7 @@ static struct pci_driver driver = { static int __init alsa_card_atiixp_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_atiixp_exit(void) diff --git a/trunk/sound/pci/atiixp_modem.c b/trunk/sound/pci/atiixp_modem.c index a6b4b8d589fd..fb7cecea846d 100644 --- a/trunk/sound/pci/atiixp_modem.c +++ b/trunk/sound/pci/atiixp_modem.c @@ -463,11 +463,6 @@ static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg) static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) { atiixp_t *chip = ac97->private_data; - if (reg == AC97_GPIO_STATUS) { - atiixp_write(chip, MODEM_OUT_GPIO, - (val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN); - return; - } snd_atiixp_codec_write(chip, ac97->num, reg, val); } @@ -668,33 +663,44 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd) { atiixp_t *chip = snd_pcm_substream_chip(substream); atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data; - int err = 0; + unsigned int reg = 0; + int i; snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL); + if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP) + return -EINVAL; + spin_lock(&chip->reg_lock); - switch(cmd) { - case SNDRV_PCM_TRIGGER_START: + + /* hook off/on: via GPIO_OUT */ + for (i = 0; i < NUM_ATI_CODECS; i++) { + if (chip->ac97[i]) { + reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS); + break; + } + } + if(cmd == SNDRV_PCM_TRIGGER_START) + reg |= AC97_GPIO_LINE1_OH; + else + reg &= ~AC97_GPIO_LINE1_OH; + reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ; + atiixp_write(chip, MODEM_OUT_GPIO, reg); + + if (cmd == SNDRV_PCM_TRIGGER_START) { dma->ops->enable_transfer(chip, 1); dma->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: + } else { dma->ops->enable_transfer(chip, 0); dma->running = 0; - break; - default: - err = -EINVAL; - break; } - if (! err) { snd_atiixp_check_bus_busy(chip); if (cmd == SNDRV_PCM_TRIGGER_STOP) { dma->ops->flush_dma(chip); snd_atiixp_check_bus_busy(chip); } - } spin_unlock(&chip->reg_lock); - return err; + return 0; } @@ -1326,7 +1332,7 @@ static struct pci_driver driver = { static int __init alsa_card_atiixp_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_atiixp_exit(void) diff --git a/trunk/sound/pci/au88x0/au88x0.c b/trunk/sound/pci/au88x0/au88x0.c index f6236c63aaaa..889b4a1a51a1 100644 --- a/trunk/sound/pci/au88x0/au88x0.c +++ b/trunk/sound/pci/au88x0/au88x0.c @@ -375,7 +375,7 @@ static struct pci_driver driver = { // initialization of the module static int __init alsa_card_vortex_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } // clean up the module diff --git a/trunk/sound/pci/azt3328.c b/trunk/sound/pci/azt3328.c index 72bba7b2d983..b8ae534125c1 100644 --- a/trunk/sound/pci/azt3328.c +++ b/trunk/sound/pci/azt3328.c @@ -1520,7 +1520,7 @@ static int __init alsa_card_azf3328_init(void) { int err; snd_azf3328_dbgcallenter(); - err = pci_register_driver(&driver); + err = pci_module_init(&driver); snd_azf3328_dbgcallleave(); return err; } diff --git a/trunk/sound/pci/bt87x.c b/trunk/sound/pci/bt87x.c index defdc5a459f0..89a7ffe5e7d7 100644 --- a/trunk/sound/pci/bt87x.c +++ b/trunk/sound/pci/bt87x.c @@ -918,7 +918,7 @@ static int __init alsa_card_bt87x_init(void) { if (load_all) driver.id_table = snd_bt87x_default_ids; - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_bt87x_exit(void) diff --git a/trunk/sound/pci/ca0106/ca0106.h b/trunk/sound/pci/ca0106/ca0106.h index da09cab405a9..deb028851056 100644 --- a/trunk/sound/pci/ca0106/ca0106.h +++ b/trunk/sound/pci/ca0106/ca0106.h @@ -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.20 * * FEATURES currently supported: * See ca0106_main.c for features. @@ -45,8 +45,6 @@ * Added I2C and SPI registers. Filled in interrupt enable. * 0.0.20 * Added GPIO info for SB Live 24bit. - * 0.0.21 - * Implement support for Line-in capture on SB Live 24bit. * * * This code was initally based on code from ALSA's emu10k1x.c which is: @@ -154,7 +152,7 @@ * bit 9 0 = Mute / 1 = Analog out. * bit 10 0 = Line-in / 1 = Mic-in. * bit 11 0 = ? / 1 = ? - * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit. + * bit 12 0 = ? / 1 = ? * bit 13 0 = ? / 1 = ? * bit 14 0 = Mute / 1 = Analog out * bit 15 0 = ? / 1 = ? @@ -477,56 +475,9 @@ /* Causes interrupts based on timer intervals. */ #define SPI 0x7a /* SPI: Serial Interface Register */ #define I2C_A 0x7b /* I2C Address. 32 bit */ -#define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */ -#define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */ -//I2C values -#define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address -#define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W -#define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value -#define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag -#define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction -#define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode +#define I2C_0 0x7c /* I2C Data Port 0. 32 bit */ +#define I2C_1 0x7d /* I2C Data Port 1. 32 bit */ -#define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC -#define I2C_A_ADC_READ 0x00000001 //To perform a read operation -#define I2C_A_ADC_START 0x00000100 //Start I2C transaction -#define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort -#define I2C_A_ADC_LAST 0x00000400 //I2C last transaction -#define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode - -#define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register -#define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register - -#define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable -#define ADC_IFC_CTRL 0x0000000b //ADC Interface Control -#define ADC_MASTER 0x0000000c //ADC Master Mode Control -#define ADC_POWER 0x0000000d //ADC PowerDown Control -#define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL -#define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR -#define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1 -#define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2 -#define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3 -#define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control -#define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control -#define ADC_MUX 0x00000015 //ADC Mux offset - -#if 0 -/* FIXME: Not tested yet. */ -#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain -#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB -#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute -#define ADC_MUTE 0x000000c0 //Value to mute ADC -#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select -#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock -#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter -#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window -#endif - -#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux -#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux -#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux -#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) -#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ #define PCM_FRONT_CHANNEL 0 @@ -557,18 +508,9 @@ struct snd_ca0106_pcm { unsigned short running; }; -typedef struct { - u32 serial; - char * name; - int ac97; - int gpio_type; - int i2c_adc; -} ca0106_details_t; - // definition of the chip-specific record struct snd_ca0106 { snd_card_t *card; - ca0106_details_t *details; struct pci_dev *pci; unsigned long port; @@ -589,7 +531,6 @@ struct snd_ca0106 { u32 spdif_bits[4]; /* s/pdif out setup */ int spdif_enable; int capture_source; - int capture_mic_line_in; struct snd_dma_buffer buffer; }; @@ -606,6 +547,3 @@ void snd_ca0106_ptr_write(ca0106_t *emu, unsigned int chn, unsigned int data); -int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value); - - diff --git a/trunk/sound/pci/ca0106/ca0106_main.c b/trunk/sound/pci/ca0106/ca0106_main.c index 95c289284267..82533b45bc8c 100644 --- a/trunk/sound/pci/ca0106/ca0106_main.c +++ b/trunk/sound/pci/ca0106/ca0106_main.c @@ -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.23 + * Version: 0.0.22 * * FEATURES currently supported: * Front, Rear and Center/LFE. @@ -77,8 +77,6 @@ * 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 - * 0.0.23 - * Implement support for Line-in capture on SB Live 24bit. * * BUGS: * Some stability problems when unloading the snd-ca0106 kernel module. @@ -138,7 +136,6 @@ #include #include #include -#include #include #include #include @@ -164,32 +161,18 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard."); #include "ca0106.h" -static ca0106_details_t ca0106_chip_details[] = { - /* AudigyLS[SB0310] */ - { .serial = 0x10021102, - .name = "AudigyLS [SB0310]", - .ac97 = 1 } , - /* Unknown AudigyLS that also says SB0310 on it */ - { .serial = 0x10051102, - .name = "AudigyLS [SB0310b]", - .ac97 = 1 } , - /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ - { .serial = 0x10061102, - .name = "Live! 7.1 24bit [SB0410]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ - { .serial = 0x10071102, - .name = "Live! 7.1 24bit [SB0413]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ - { .serial = 0x10091462, - .name = "MSI K8N Diamond MB [SB0438]", - .gpio_type = 1, - .i2c_adc = 1 } , - { .serial = 0, - .name = "AudigyLS [Unknown]" } +typedef struct { + u32 serial; + char * name; +} ca0106_names_t; + +static ca0106_names_t ca0106_chip_names[] = { + { 0x10021102, "AudigyLS [SB0310]"} , + { 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]" } }; /* hardware definition */ @@ -217,10 +200,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, - .rate_min = 44100, - .rate_max = 192000, + .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 = ((65536 - 64) * 8), @@ -263,62 +246,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu, spin_unlock_irqrestore(&emu->emu_lock, flags); } -int snd_ca0106_i2c_write(ca0106_t *emu, - u32 reg, - u32 value) -{ - u32 tmp; - int timeout=0; - int status; - int retry; - if ((reg > 0x7f) || (value > 0x1ff)) - { - snd_printk("i2c_write: invalid values.\n"); - return -EINVAL; - } - - tmp = reg << 25 | value << 16; - /* Not sure what this I2C channel controls. */ - /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ - - /* This controls the I2C connected to the WM8775 ADC Codec */ - snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp); - - for(retry=0;retry<10;retry++) - { - /* Send the data to i2c */ - tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); - tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); - tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); - snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); - - /* Wait till the transaction ends */ - while(1) - { - status = snd_ca0106_ptr_read(emu, I2C_A, 0); - //snd_printk("I2C:status=0x%x\n", status); - timeout++; - if((status & I2C_A_ADC_START)==0) - break; - - if(timeout>1000) - break; - } - //Read back and see if the transaction is successful - if((status & I2C_A_ADC_ABORT)==0) - break; - } - - if(retry==10) - { - snd_printk("Writing to ADC failed!\n"); - return -EINVAL; - } - - return 0; -} - - static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) { unsigned long flags; @@ -332,7 +259,11 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) { - kfree(runtime->private_data); + ca0106_pcm_t *epcm = runtime->private_data; + + if (epcm) { + kfree(epcm); + } } /* open_playback callback */ @@ -607,61 +538,6 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream) snd_pcm_runtime_t *runtime = substream->runtime; ca0106_pcm_t *epcm = runtime->private_data; int channel = epcm->channel_id; - u32 hcfg_mask = HCFG_CAPTURE_S32_LE; - u32 hcfg_set = 0x00000000; - u32 hcfg; - u32 over_sampling=0x2; - u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */ - u32 reg71_set = 0; - u32 reg71; - - //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); - //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); - /* reg71 controls ADC rate. */ - switch (runtime->rate) { - case 44100: - reg71_set = 0x00004000; - break; - case 48000: - reg71_set = 0; - break; - case 96000: - reg71_set = 0x00008000; - over_sampling=0xa; - break; - case 192000: - reg71_set = 0x0000c000; - over_sampling=0xa; - break; - default: - reg71_set = 0; - break; - } - /* Format is a global setting */ - /* FIXME: Only let the first channel accessed set this. */ - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - hcfg_set = 0; - break; - case SNDRV_PCM_FORMAT_S32_LE: - hcfg_set = HCFG_CAPTURE_S32_LE; - break; - default: - hcfg_set = 0; - break; - } - hcfg = inl(emu->port + HCFG) ; - hcfg = (hcfg & ~hcfg_mask) | hcfg_set; - outl(hcfg, emu->port + HCFG); - reg71 = snd_ca0106_ptr_read(emu, 0x71, 0); - reg71 = (reg71 & ~reg71_mask) | reg71_set; - snd_ca0106_ptr_write(emu, 0x71, 0, reg71); - if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ - snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */ - } - - //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); snd_ca0106_ptr_write(emu, 0x13, channel, 0); snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); @@ -934,7 +810,6 @@ static int snd_ca0106_ac97(ca0106_t *chip) memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - ac97.scaps = AC97_SCAP_NO_SPDIF; return snd_ac97_mixer(pbus, &ac97, &chip->ac97); } @@ -1118,7 +993,6 @@ static int __devinit snd_ca0106_create(snd_card_t *card, ca0106_t **rchip) { ca0106_t *chip; - ca0106_details_t *c; int err; int ch; static snd_device_ops_t ops = { @@ -1129,8 +1003,8 @@ static int __devinit snd_ca0106_create(snd_card_t *card, if ((err = pci_enable_device(pci)) < 0) return err; - if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || - pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { + if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 || + pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) { printk(KERN_ERR "error to set 32bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; @@ -1180,15 +1054,6 @@ static int __devinit snd_ca0106_create(snd_card_t *card, printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, chip->revision, chip->serial); #endif - strcpy(card->driver, "CA0106"); - strcpy(card->shortname, "CA0106"); - - for (c=ca0106_chip_details; c->serial; c++) { - if (c->serial == chip->serial) break; - } - chip->details = c; - sprintf(card->longname, "%s at 0x%lx irq %i", - c->name, chip->port, chip->irq); outl(0, chip->port + INTE); @@ -1248,7 +1113,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card, //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */ /* Analog or Digital output */ snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */ + snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000b0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers */ chip->spdif_enable = 0; /* Set digital SPDIF output off */ chip->capture_source = 3; /* Set CAPTURE_SOURCE */ //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ @@ -1273,11 +1138,13 @@ static int __devinit snd_ca0106_create(snd_card_t *card, 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->details->gpio_type == 1) { /* 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 */ - outl(0x005f5301, chip->port+GPIO); /* Analog */ + outl(0x005f4300, chip->port+GPIO); /* Analog */ } else { outl(0x0, chip->port+GPIO); outl(0x005f03a3, chip->port+GPIO); /* Analog */ @@ -1290,10 +1157,6 @@ static int __devinit snd_ca0106_create(snd_card_t *card, //outl(0x00000009, chip->port+HCFG); outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ - if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ - snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ - } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_ca0106_free(chip); @@ -1309,6 +1172,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, static int dev; snd_card_t *card; ca0106_t *chip; + ca0106_names_t *c; int err; if (dev >= SNDRV_CARDS) @@ -1343,7 +1207,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, snd_card_free(card); return err; } - if (chip->details->ac97 == 1) { /* 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; @@ -1356,6 +1222,15 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, snd_ca0106_proc_init(chip); + strcpy(card->driver, "CA0106"); + strcpy(card->shortname, "CA0106"); + + for (c=ca0106_chip_names; c->serial; c++) { + if (c->serial == chip->serial) break; + } + sprintf(card->longname, "%s at 0x%lx irq %i", + c->name, chip->port, chip->irq); + if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; @@ -1392,7 +1267,7 @@ static int __init alsa_card_ca0106_init(void) { int err; - if ((err = pci_register_driver(&driver)) > 0) + if ((err = pci_module_init(&driver)) > 0) return err; return 0; diff --git a/trunk/sound/pci/ca0106/ca0106_mixer.c b/trunk/sound/pci/ca0106/ca0106_mixer.c index 0e5e9ce0ff28..97bed1b0899d 100644 --- a/trunk/sound/pci/ca0106/ca0106_mixer.c +++ b/trunk/sound/pci/ca0106/ca0106_mixer.c @@ -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.17 + * Version: 0.0.16 * * FEATURES currently supported: * See ca0106_main.c for features. @@ -37,8 +37,6 @@ * Separated ca0106.c into separate functional .c files. * 0.0.16 * Modified Copyright message. - * 0.0.17 - * Implement Mic and Line in Capture. * * This code was initally based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes @@ -115,7 +113,7 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol, } else { /* Analog */ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); + snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000); snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); mask = inl(emu->port + GPIO) | 0x101; @@ -185,65 +183,6 @@ static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata = .put = snd_ca0106_capture_source_put }; -static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) -{ - static char *texts[2] = { "Line in", "Mic in" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ca0106_capture_mic_line_in_get(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - ca0106_t *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in; - return 0; -} - -static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - ca0106_t *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 tmp; - - val = ucontrol->value.enumerated.item[0] ; - change = (emu->capture_mic_line_in != val); - if (change) { - emu->capture_mic_line_in = val; - if (val) { - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ - tmp = inl(emu->port+GPIO) & ~0x400; - tmp = tmp | 0x400; - outl(tmp, emu->port+GPIO); - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); - } else { - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ - tmp = inl(emu->port+GPIO) & ~0x400; - outl(tmp, emu->port+GPIO); - snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); - } - } - return change; -} - -static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic/Line in Capture", - .info = snd_ca0106_capture_mic_line_in_info, - .get = snd_ca0106_capture_mic_line_in_get, - .put = snd_ca0106_capture_mic_line_in_put -}; - static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; @@ -498,7 +437,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe = static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Side Volume", + .name = "Analog Unknown Volume", .info = snd_ca0106_volume_info, .get = snd_ca0106_volume_get_analog_unknown, .put = snd_ca0106_volume_put_analog_unknown @@ -681,11 +620,10 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; - if (emu->details->i2c_adc == 1) { - if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; + if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) { + /* already defined by ac97, remove it */ + /* FIXME: or do we need both controls? */ + remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT)); } if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL) return -ENOMEM; diff --git a/trunk/sound/pci/ca0106/ca0106_proc.c b/trunk/sound/pci/ca0106/ca0106_proc.c index 1c9cc821d1b9..afb711421e47 100644 --- a/trunk/sound/pci/ca0106/ca0106_proc.c +++ b/trunk/sound/pci/ca0106/ca0106_proc.c @@ -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.18 + * Version: 0.0.17 * * FEATURES currently supported: * See ca0106_main.c for features. @@ -39,9 +39,7 @@ * Modified Copyright message. * 0.0.17 * Add iec958 file in proc file system to show status of SPDIF in. - * 0.0.18 - * Implement support for Line-in capture on SB Live 24bit. - * + * * This code was initally based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * @@ -97,7 +95,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = { }; -static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value) +void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value) { int i; u32 status[4]; @@ -409,20 +407,6 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry, } } -static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry, - snd_info_buffer_t * buffer) -{ - ca0106_t *emu = entry->private_data; - char line[64]; - unsigned int reg, val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if ((reg <= 0x7f) || (val <= 0x1ff)) { - snd_ca0106_i2c_write(emu, reg, val); - } - } -} int __devinit snd_ca0106_proc_init(ca0106_t * emu) { @@ -434,7 +418,6 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); entry->c.text.write_size = 64; entry->c.text.write = snd_ca0106_proc_reg_write32; - entry->mode |= S_IWUSR; } if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); @@ -444,14 +427,6 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); entry->c.text.write_size = 64; entry->c.text.write = snd_ca0106_proc_reg_write; - entry->mode |= S_IWUSR; -// entry->private_data = emu; - } - if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { - snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); - entry->c.text.write_size = 64; - entry->c.text.write = snd_ca0106_proc_i2c_write; - entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) diff --git a/trunk/sound/pci/cmipci.c b/trunk/sound/pci/cmipci.c index b4503385ea69..113208fbde1b 100644 --- a/trunk/sound/pci/cmipci.c +++ b/trunk/sound/pci/cmipci.c @@ -519,50 +519,40 @@ inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd) } /* bit operations for dword register */ -static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) +static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) { - unsigned int val, oval; - val = oval = inl(cm->iobase + cmd); + unsigned int val; + val = inl(cm->iobase + cmd); val |= flag; - if (val == oval) - return 0; outl(val, cm->iobase + cmd); - return 1; } -static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) +static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) { - unsigned int val, oval; - val = oval = inl(cm->iobase + cmd); + unsigned int val; + val = inl(cm->iobase + cmd); val &= ~flag; - if (val == oval) - return 0; outl(val, cm->iobase + cmd); - return 1; } +#if 0 // not used /* bit operations for byte register */ -static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) +static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) { - unsigned char val, oval; - val = oval = inb(cm->iobase + cmd); + unsigned char val; + val = inb(cm->iobase + cmd); val |= flag; - if (val == oval) - return 0; outb(val, cm->iobase + cmd); - return 1; } -static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) +static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) { - unsigned char val, oval; - val = oval = inb(cm->iobase + cmd); + unsigned char val; + val = inb(cm->iobase + cmd); val &= ~flag; - if (val == oval) - return 0; outb(val, cm->iobase + cmd); - return 1; } +#endif /* @@ -2260,8 +2250,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); #endif DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); -// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); -// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); +DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); +DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); @@ -2310,114 +2300,10 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v } -static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) -{ - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2; - 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 inline unsigned int get_line_in_mode(cmipci_t *cm) -{ - unsigned int val; - if (cm->chip_version >= 39) { - val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); - if (val & CM_LINE_AS_BASS) - return 2; - } - val = snd_cmipci_read_b(cm, CM_REG_MIXER1); - if (val & CM_SPK4) - return 1; - return 0; -} - -static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) -{ - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&cm->reg_lock); - ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) -{ - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - int change; - - spin_lock_irq(&cm->reg_lock); - if (ucontrol->value.enumerated.item[0] == 2) - change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); - else - change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); - if (ucontrol->value.enumerated.item[0] == 1) - change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); - else - change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); - spin_unlock_irq(&cm->reg_lock); - return change; -} - -static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) -{ - static char *texts[2] = { "Mic-In", "Center/LFE Output" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - 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_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) -{ - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - /* same bit as spdi_phase */ - spin_lock_irq(&cm->reg_lock); - ucontrol->value.enumerated.item[0] = - (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0; - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) -{ - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - int change; - - spin_lock_irq(&cm->reg_lock); - if (ucontrol->value.enumerated.item[0]) - change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); - else - change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); - spin_unlock_irq(&cm->reg_lock); - return change; -} - /* both for CM8338/8738 */ static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), - { - .name = "Line-In Mode", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_cmipci_line_in_mode_info, - .get = snd_cmipci_line_in_mode_get, - .put = snd_cmipci_line_in_mode_put, - }, + DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear), }; /* for non-multichannel chips */ @@ -2455,15 +2341,10 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = { /* only for model 039 or later */ static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { + DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass), DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), - { - .name = "Mic-In Mode", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_cmipci_mic_in_mode_info, - .get = snd_cmipci_mic_in_mode_get, - .put = snd_cmipci_mic_in_mode_put, - } + DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */ }; /* card control switches */ @@ -3063,7 +2944,7 @@ static struct pci_driver driver = { static int __init alsa_card_cmipci_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_cmipci_exit(void) diff --git a/trunk/sound/pci/cs4281.c b/trunk/sound/pci/cs4281.c index b6e1854e9389..d7e06b3caf97 100644 --- a/trunk/sound/pci/cs4281.c +++ b/trunk/sound/pci/cs4281.c @@ -206,10 +206,7 @@ MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled)."); #define BA0_PMCS 0x0344 /* Power Management Control/Status */ #define BA0_CWPR 0x03e0 /* Configuration Write Protect */ - #define BA0_EPPMC 0x03e4 /* Extended PCI Power Management Control */ -#define BA0_EPPMC_FPDN (1<<14) /* Full Power DowN */ - #define BA0_GPIOR 0x03e8 /* GPIO Pin Interface Register */ #define BA0_SPMC 0x03ec /* Serial Port Power Management Control (& ASDIN2 enable) */ @@ -1464,11 +1461,6 @@ static int snd_cs4281_chip_init(cs4281_t *chip) int timeout; int retry_count = 2; - /* Having EPPMC.FPDN=1 prevent proper chip initialisation */ - tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC); - if (tmp & BA0_EPPMC_FPDN) - snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN); - __retry: tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); if (tmp != BA0_CFLR_DEFAULT) { @@ -2132,7 +2124,7 @@ static struct pci_driver driver = { static int __init alsa_card_cs4281_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_cs4281_exit(void) diff --git a/trunk/sound/pci/cs46xx/cs46xx.c b/trunk/sound/pci/cs46xx/cs46xx.c index db212ecd792a..25d6466a867c 100644 --- a/trunk/sound/pci/cs46xx/cs46xx.c +++ b/trunk/sound/pci/cs46xx/cs46xx.c @@ -171,7 +171,7 @@ static struct pci_driver driver = { static int __init alsa_card_cs46xx_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_cs46xx_exit(void) diff --git a/trunk/sound/pci/cs46xx/cs46xx_lib.c b/trunk/sound/pci/cs46xx/cs46xx_lib.c index fd4c50c88bc9..5f2ffb7efa06 100644 --- a/trunk/sound/pci/cs46xx/cs46xx_lib.c +++ b/trunk/sound/pci/cs46xx/cs46xx_lib.c @@ -1295,7 +1295,8 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = { static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime) { - kfree(runtime->private_data); + cs46xx_pcm_t * cpcm = runtime->private_data; + kfree(cpcm); } static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id) diff --git a/trunk/sound/pci/emu10k1/emu10k1.c b/trunk/sound/pci/emu10k1/emu10k1.c index 2085a998eaeb..6446afe19d80 100644 --- a/trunk/sound/pci/emu10k1/emu10k1.c +++ b/trunk/sound/pci/emu10k1/emu10k1.c @@ -228,7 +228,7 @@ static struct pci_driver driver = { static int __init alsa_card_emu10k1_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_emu10k1_exit(void) diff --git a/trunk/sound/pci/emu10k1/emu10k1_main.c b/trunk/sound/pci/emu10k1/emu10k1_main.c index a341e758acde..c3c96f9f2c7f 100644 --- a/trunk/sound/pci/emu10k1/emu10k1_main.c +++ b/trunk/sound/pci/emu10k1/emu10k1_main.c @@ -170,7 +170,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ + if (emu->audigy && emu->revision == 4) { /* audigy2 */ /* Hacks for Alice3 to work independent of haP16V driver */ u32 tmp; @@ -189,7 +189,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) /* Enabled Phased (8-channel) P16V playback */ outl(0x0201, emu->port + HCFG2); /* Set playback routing. */ - snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); + snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4); } if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */ /* Hacks for Alice3 to work independent of haP16V driver */ @@ -600,7 +600,7 @@ static int snd_emu10k1_free(emu10k1_t *emu) if (emu->port) pci_release_regions(emu->pci); pci_disable_device(emu->pci); - if (emu->card_capabilities->ca0151_chip) /* P16V */ + if (emu->audigy && emu->revision == 4) /* P16V */ snd_p16v_free(emu); kfree(emu); return 0; @@ -612,24 +612,21 @@ static int snd_emu10k1_dev_free(snd_device_t *device) return snd_emu10k1_free(emu); } +/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */ + static emu_chip_details_t emu_chip_details[] = { /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0108_chip = 1, - .spk71 = 1, - .ac97_chip = 1} , + .spk71 = 1} , {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", - .id = "Audigy2", .emu10k2_chip = 1, - .ca0108_chip = 1, - .ac97_chip = 1} , + .ca0108_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, .ca0151_chip = 1, @@ -638,7 +635,6 @@ static emu_chip_details_t emu_chip_details[] = { .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, .ca0151_chip = 1, @@ -647,7 +643,6 @@ static emu_chip_details_t emu_chip_details[] = { .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, .ca0151_chip = 1, @@ -656,7 +651,6 @@ static emu_chip_details_t emu_chip_details[] = { .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, .driver = "Audigy2", .name = "Audigy 2 [SB0240]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, .ca0151_chip = 1, @@ -665,165 +659,35 @@ static emu_chip_details_t emu_chip_details[] = { .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, .driver = "Audigy2", .name = "Audigy 2 EX [1005]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, .ca0151_chip = 1, .spdif_bug = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", - .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, .ca0151_chip = 1, .spk71 = 1, .spdif_bug = 1, .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, - .driver = "Audigy2", .name = "Audigy 2 [Unknown]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052, - .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, - .driver = "Audigy", .name = "Audigy 1 [SB0090]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, - .driver = "Audigy", .name = "Audigy 1 [SB0090]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, - .driver = "Audigy", .name = "Audigy 1 [Unknown]", - .id = "Audigy", + .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]", .emu10k2_chip = 1, .ca0102_chip = 1, - .ac97_chip = 1} , + .spdif_bug = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, .driver = "EMU10K1", .name = "E-mu APS [4001]", - .id = "APS", .emu10k1_chip = 1, .ecard = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, - .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, .driver = "EMU10K1", .name = "SB Live 5.1", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, - .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", - .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, - .driver = "EMU10K1", .name = "SBLive! [CT4620]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, - .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4831]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, - .driver = "EMU10K1", .name = "SBLive! Value [SB0060]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, - .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102, - .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102, - .driver = "EMU10K1", .name = "SBLive! [SB0105]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .driver = "EMU10K1", .name = "SB Live [Unknown]", - .id = "Live", .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , + .ac97_chip = 1} , { } /* terminator */ }; @@ -874,15 +738,13 @@ int __devinit snd_emu10k1_create(snd_card_t * card, emu->revision = revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); + emu->card_type = EMU10K1_CARD_CREATIVE; snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model); for (c = emu_chip_details; c->vendor; c++) { if (c->vendor == pci->vendor && c->device == pci->device) { - if (c->subsystem && c->subsystem != emu->serial) - continue; - if (c->revision && c->revision != emu->revision) - continue; - break; + if (c->subsystem == emu->serial) break; + if (c->subsystem == 0) break; } } if (c->vendor == 0) { @@ -897,23 +759,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card, else snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial); - if (!*card->id && c->id) { - int i, n = 0; - strlcpy(card->id, c->id, sizeof(card->id)); - for (;;) { - for (i = 0; i < snd_ecards_limit; i++) { - if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id)) - break; - } - if (i >= snd_ecards_limit) - break; - n++; - if (n >= SNDRV_CARDS) - break; - snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n); - } - } - is_audigy = emu->audigy = c->emu10k2_chip; /* set the DMA transfer mask */ @@ -971,6 +816,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card, pci_set_master(pci); + if (c->ecard) { + emu->card_type = EMU10K1_CARD_EMUAPS; + emu->APS = 1; + } + if (! c->ac97_chip) + emu->no_ac97 = 1; + + emu->spk71 = c->spk71; + emu->fx8010.fxbus_mask = 0x303f; if (extin_mask == 0) extin_mask = 0x3fcf; @@ -979,7 +833,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card, emu->fx8010.extin_mask = extin_mask; emu->fx8010.extout_mask = extout_mask; - if (emu->card_capabilities->ecard) { + if (emu->APS) { if ((err = snd_emu10k1_ecard_init(emu)) < 0) { snd_emu10k1_free(emu); return err; diff --git a/trunk/sound/pci/emu10k1/emu10k1x.c b/trunk/sound/pci/emu10k1/emu10k1x.c index e90c5ddd1d17..27dfd8ddddf4 100644 --- a/trunk/sound/pci/emu10k1/emu10k1x.c +++ b/trunk/sound/pci/emu10k1/emu10k1x.c @@ -361,7 +361,10 @@ static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value) static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime) { - kfree(runtime->private_data); + emu10k1x_pcm_t *epcm = runtime->private_data; + + if (epcm) + kfree(epcm); } static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice) @@ -1072,7 +1075,6 @@ static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu) snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); entry->c.text.write_size = 64; entry->c.text.write = snd_emu10k1x_proc_reg_write; - entry->mode |= S_IWUSR; entry->private_data = emu; } @@ -1625,7 +1627,7 @@ static int __init alsa_card_emu10k1x_init(void) { int err; - if ((err = pci_register_driver(&driver)) > 0) + if ((err = pci_module_init(&driver)) > 0) return err; return 0; diff --git a/trunk/sound/pci/emu10k1/emufx.c b/trunk/sound/pci/emu10k1/emufx.c index 0529fb281125..b9fa2e887fee 100644 --- a/trunk/sound/pci/emu10k1/emufx.c +++ b/trunk/sound/pci/emu10k1/emufx.c @@ -1077,7 +1077,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu) gpr += 2; /* PCM Side Playback (independent from stereo mix) */ - if (emu->card_capabilities->spk71) { + if (emu->spk71) { A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100); @@ -1145,14 +1145,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L); A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R); snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume", + emu->no_ac97 ? "CD Playback Volume" : "Audigy CD Playback Volume", gpr, 0); gpr += 2; /* Audigy CD Capture Volume */ A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L); A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R); snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume", + emu->no_ac97 ? "CD Capture Volume" : "Audigy CD Capture Volume", gpr, 0); gpr += 2; @@ -1171,14 +1171,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L); A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R); snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume", + emu->no_ac97 ? "Line Playback Volume" : "Line2 Playback Volume", gpr, 0); gpr += 2; /* Line2 Capture Volume */ A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L); A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R); snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume", + emu->no_ac97 ? "Line Capture Volume" : "Line2 Capture Volume", gpr, 0); gpr += 2; @@ -1197,14 +1197,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L); A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R); snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume", + emu->no_ac97 ? "Aux Playback Volume" : "Aux2 Playback Volume", gpr, 0); gpr += 2; /* Aux2 Capture Volume */ A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L); A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R); snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume", + emu->no_ac97 ? "Aux Capture Volume" : "Aux2 Capture Volume", gpr, 0); gpr += 2; @@ -1232,7 +1232,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0); gpr++; - if (emu->card_capabilities->spk71) { + if (emu->spk71) { /* Stereo Mix Side Playback */ A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); @@ -1266,7 +1266,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */ A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */ A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */ - if (emu->card_capabilities->spk71) { + if (emu->spk71) { A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */ A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */ } @@ -1359,7 +1359,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); - if (emu->card_capabilities->spk71) + if (emu->spk71) A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS); /* headphone */ @@ -1982,27 +1982,22 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000); /* EFX capture - capture the 16 EXTINS */ - if (emu->card_capabilities->sblive51) { - /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER - * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording. - * - * Since only 14 of the 16 EXTINs are used, this is not a big problem. - * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture - * 0 and 3, then the rest of the EXTINs to the corresponding FX capture - * channel. Multitrack recorders will still see the center/lfe output signal - * on the second and third channels. - */ - OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0)); - OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1)); - OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2)); - OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3)); - for (z = 4; z < 14; z++) - OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); - } else { - for (z = 0; z < 16; z++) - OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); + OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0)); + OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1)); + OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2)); + OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3)); + /* Dont connect anything to FXBUS2 1 and 2. These are shared with + * Center/LFE on the SBLive 5.1. The kX driver only changes the + * routing when it detects an SBLive 5.1. + * + * Since only 14 of the 16 EXTINs are used, this is not a big problem. + * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture + * 0 and 3, then the rest of the EXTINs to the corresponding FX capture + * channel. + */ + for (z = 4; z < 14; z++) { + OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); } - if (gpr > tmp) { snd_BUG(); @@ -2133,6 +2128,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info) int res; memset(info, 0, sizeof(info)); + info->card = emu->card_type; info->internal_tram_size = emu->fx8010.itram_size; info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; fxbus = fxbuses; diff --git a/trunk/sound/pci/emu10k1/emumixer.c b/trunk/sound/pci/emu10k1/emumixer.c index 6be82c5fe138..044663d31aa7 100644 --- a/trunk/sound/pci/emu10k1/emumixer.c +++ b/trunk/sound/pci/emu10k1/emumixer.c @@ -68,7 +68,6 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol, return 0; } -#if 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"}; @@ -153,7 +152,6 @@ static snd_kcontrol_new_t snd_audigy_spdif_output_rate = .get = snd_audigy_spdif_output_rate_get, .put = snd_audigy_spdif_output_rate_put }; -#endif static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) @@ -793,7 +791,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) NULL }; - if (emu->card_capabilities->ac97_chip) { + if (!emu->no_ac97) { ac97_bus_t *pbus; ac97_template_t ac97; static ac97_bus_ops_t ops = { @@ -835,7 +833,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) for (; *c; c++) remove_ctl(card, *c); } else { - if (emu->card_capabilities->ecard) + if (emu->APS) strcpy(emu->card->mixername, "EMU APS"); else if (emu->audigy) strcpy(emu->card->mixername, "SB Audigy"); @@ -920,7 +918,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) mix->attn[0] = 0xffff; } - if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */ + if (! emu->APS) { /* FIXME: APS has these controls? */ /* sb live! and audigy */ if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) return -ENOMEM; @@ -937,20 +935,18 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; -#if 0 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; -#endif - } else if (! emu->card_capabilities->ecard) { + } else if (! emu->APS) { /* sb live! */ if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; } - if (emu->card_capabilities->ca0151_chip) { /* P16V */ + if (emu->audigy && emu->revision == 4) { /* P16V */ if ((err = snd_p16v_mixer(emu))) return err; } diff --git a/trunk/sound/pci/emu10k1/emupcm.c b/trunk/sound/pci/emu10k1/emupcm.c index 520b99af5f55..d1c2a02c486b 100644 --- a/trunk/sound/pci/emu10k1/emupcm.c +++ b/trunk/sound/pci/emu10k1/emupcm.c @@ -262,7 +262,7 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target) * * returns: cache invalidate size in samples */ -static inline int emu10k1_ccis(int stereo, int w_16) +static int inline emu10k1_ccis(int stereo, int w_16) { if (w_16) { return stereo ? 24 : 26; @@ -991,7 +991,9 @@ static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activa static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime) { - kfree(runtime->private_data); + emu10k1_pcm_t *epcm = runtime->private_data; + + kfree(epcm); } static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream) diff --git a/trunk/sound/pci/emu10k1/emuproc.c b/trunk/sound/pci/emu10k1/emuproc.c index cc22707c91fa..d990d5eb45a8 100644 --- a/trunk/sound/pci/emu10k1/emuproc.c +++ b/trunk/sound/pci/emu10k1/emuproc.c @@ -30,7 +30,6 @@ #include #include #include -#include "p16v.h" static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu, snd_info_buffer_t * buffer, @@ -45,34 +44,28 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu, unsigned int status, rate = 0; status = snd_emu10k1_ptr_read(emu, status_reg, 0); + if (rate_reg > 0) + rate = snd_emu10k1_ptr_read(emu, rate_reg, 0); snd_iprintf(buffer, "\n%s\n", title); - if (status != 0xffffffff) { - snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no"); - snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no"); - snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no"); - snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]); - snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6); - snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8); - snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy"); - snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16); - snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]); - snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]); - snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]); - - if (rate_reg > 0) { - rate = snd_emu10k1_ptr_read(emu, rate_reg, 0); - snd_iprintf(buffer, "S/PDIF Valid : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off"); - snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off"); - snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off"); - /* From ((Rate * 48000 ) / 262144); */ - snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11); - } - } else { - snd_iprintf(buffer, "No signal detected.\n"); + snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no"); + snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no"); + snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no"); + snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]); + snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6); + snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8); + snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy"); + snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16); + snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]); + snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]); + snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]); + + if (rate_reg > 0) { + snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off"); + snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off"); + snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE); } - } static void snd_emu10k1_proc_read(snd_info_entry_t *entry, @@ -189,7 +182,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry, snd_iprintf(buffer, "EMU10K1\n\n"); snd_iprintf(buffer, "Card : %s\n", - emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative")); + emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative")); snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size); snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2); snd_iprintf(buffer, "\n"); @@ -230,35 +223,15 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry, snd_iprintf(buffer, "\nAll FX Outputs :\n"); for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++) snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); -} - -static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry, - snd_info_buffer_t * buffer) -{ - emu10k1_t *emu = entry->private_data; - snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); - snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); -#if 0 + 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); + snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1); + snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS); + snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS); val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); snd_iprintf(buffer, "\nZoomed Video\n"); snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off"); snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE); -#endif -} - -static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry, - snd_info_buffer_t * buffer) -{ - static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 }; - emu10k1_t *emu = entry->private_data; - unsigned int val, tmp, n; - val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0); - tmp = (val >> 16) & 0x8; - for (n=0;n<4;n++) { - tmp = val >> (16 + (n*4)); - if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]); - else snd_iprintf(buffer, "Channel %d: No input\n", n); - } } static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, @@ -527,46 +500,32 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu) snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); entry->c.text.write_size = 64; entry->c.text.write = snd_emu_proc_io_reg_write; - entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { 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; - entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { 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; - entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { 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; - entry->mode |= S_IWUSR; } if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { 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; - entry->mode |= S_IWUSR; } #endif if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); - if (emu->card_capabilities->emu10k2_chip) { - if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) - snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read); - } - if (emu->card_capabilities->ca0151_chip) { - if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) - snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read); - } - if (! snd_card_proc_new(emu->card, "voices", &entry)) snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); diff --git a/trunk/sound/pci/emu10k1/irq.c b/trunk/sound/pci/emu10k1/irq.c index cd8460d56752..b81a7cafff39 100644 --- a/trunk/sound/pci/emu10k1/irq.c +++ b/trunk/sound/pci/emu10k1/irq.c @@ -37,7 +37,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) int handled = 0; while ((status = inl(emu->port + IPR)) != 0) { - //printk("emu10k1 irq - status = 0x%x\n", status); + // printk("irq - status = 0x%x\n", status); orig_status = status; handled = 1; if (status & IPR_PCIERROR) { @@ -147,36 +147,9 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); status &= ~IPR_FXDSP; } - if (status & IPR_P16V) { - while ((status2 = inl(emu->port + IPR2)) != 0) { - u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ - emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]); - emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice); - - //printk(KERN_INFO "status2=0x%x\n", status2); - orig_status2 = status2; - if(status2 & mask) { - if(pvoice->use) { - snd_pcm_period_elapsed(pvoice->epcm->substream); - } else { - snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); - } - } - if(status2 & 0x110000) { - //printk(KERN_INFO "capture int found\n"); - if(cvoice->use) { - //printk(KERN_INFO "capture period_elapsed\n"); - snd_pcm_period_elapsed(cvoice->epcm->substream); - } - } - outl(orig_status2, emu->port + IPR2); /* ack all */ - } - status &= ~IPR_P16V; - } - if (status) { unsigned int bits; - snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); + //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); //make sure any interrupts we don't handle are disabled: bits = INTE_FXDSPENABLE | INTE_PCIERRORENABLE | @@ -197,5 +170,20 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) } outl(orig_status, emu->port + IPR); /* ack all */ } + if (emu->audigy && emu->revision == 4) { /* P16V */ + while ((status2 = inl(emu->port + IPR2)) != 0) { + u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ + emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]); + orig_status2 = status2; + if(status2 & mask) { + if(pvoice->use) { + snd_pcm_period_elapsed(pvoice->epcm->substream); + } else { + snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); + } + } + outl(orig_status2, emu->port + IPR2); /* ack all */ + } + } return IRQ_RETVAL(handled); } diff --git a/trunk/sound/pci/emu10k1/p16v.c b/trunk/sound/pci/emu10k1/p16v.c index 98f980189892..d03cb2fefc9e 100644 --- a/trunk/sound/pci/emu10k1/p16v.c +++ b/trunk/sound/pci/emu10k1/p16v.c @@ -1,7 +1,7 @@ /* * Copyright (c) by James Courtier-Dutton * Driver p16v chips - * Version: 0.25 + * Version: 0.22 * * FEATURES currently supported: * Output fixed at S32_LE, 2 channel to hw:0,0 @@ -41,15 +41,7 @@ * Integrated with snd-emu10k1 driver. * 0.22 * Removed #if 0 ... #endif - * 0.23 - * Implement different capture rates. - * 0.24 - * Implement different capture source channels. - * e.g. When HD Capture source is set to SPDIF, - * setting HD Capture channel to 0 captures from CDROM digital input. - * setting HD Capture channel to 1 captures from SPDIF in. - * 0.25 - * Include capture buffer sizes. + * * * BUGS: * Some stability problems when unloading the snd-p16v kernel module. @@ -127,41 +119,22 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = { SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ - .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .rate_min = 44100, + .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 , + .rate_min = 48000, .rate_max = 192000, .channels_min = 8, .channels_max = 8, - .buffer_bytes_max = ((65536 - 64) * 8), + .buffer_bytes_max = (32*1024), .period_bytes_min = 64, - .period_bytes_max = (65536 - 64), + .period_bytes_max = (16*1024), .periods_min = 2, .periods_max = 8, .fifo_size = 0, }; -static snd_pcm_hardware_t snd_p16v_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (65536 - 64), - .period_bytes_min = 64, - .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */ - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime) { - emu10k1_pcm_t *epcm = runtime->private_data; + snd_pcm_t *epcm = runtime->private_data; if (epcm) { //snd_printk("epcm free: %p\n", epcm); @@ -205,63 +178,15 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in return 0; } -/* open_capture callback */ -static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id) -{ - emu10k1_t *emu = snd_pcm_substream_chip(substream); - emu10k1_voice_t *channel = &(emu->p16v_capture_voice); - emu10k1_pcm_t *epcm; - snd_pcm_runtime_t *runtime = substream->runtime; - int err; - - epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL); - //snd_printk("epcm kcalloc: %p\n", epcm); - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; - //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); - - runtime->private_data = epcm; - runtime->private_free = snd_p16v_pcm_free_substream; - - runtime->hw = snd_p16v_capture_hw; - - channel->emu = emu; - channel->number = channel_id; - - channel->use=1; - //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); - //channel->interrupt = snd_p16v_pcm_channel_interrupt; - channel->epcm=epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - return 0; -} - /* close callback */ static int snd_p16v_pcm_close_playback(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; - emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0; - /* FIXME: maybe zero others */ - return 0; -} - -/* close callback */ -static int snd_p16v_pcm_close_capture(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; - emu->p16v_capture_voice.use=0; - /* FIXME: maybe zero others */ + //emu10k1_pcm_t *epcm = runtime->private_data; + emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0; +/* FIXME: maybe zero others */ return 0; } @@ -270,55 +195,36 @@ static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream) return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL); } -static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream) -{ - // Only using channel 0 for now, but the card has 2 channels. - return snd_p16v_pcm_open_capture_channel(substream, 0); -} - /* hw_params callback */ static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream, snd_pcm_hw_params_t * hw_params) { int result; + //snd_printk("hw_params alloc: substream=%p\n", substream); result = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + //snd_printk("hw_params alloc: result=%d\n", result); + //dump_stack(); return result; } -/* hw_params callback */ -static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t * hw_params) -{ - int result; - result = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - return result; -} - - /* hw_free callback */ static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream) { int result; + //snd_printk("hw_params free: substream=%p\n", substream); result = snd_pcm_lib_free_pages(substream); + //snd_printk("hw_params free: result=%d\n", result); + //dump_stack(); return result; } -/* hw_free callback */ -static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream) -{ - int result; - result = snd_pcm_lib_free_pages(substream); - return result; -} - - /* prepare playback callback */ static int snd_p16v_pcm_prepare_playback(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; int channel = substream->pcm->device - emu->p16v_device_offset; u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); @@ -331,21 +237,23 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); switch (runtime->rate) { case 44100: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080); + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */ + break; + case 48000: + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */ break; case 96000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040); + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */ break; case 192000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020); + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */ break; - case 48000: default: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000); + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */ break; } /* FIXME: Check emu->buffer.size before actually writing to it. */ - for(i=0; i < runtime->periods; i++) { + for(i=0; i < runtime->periods; i++) { table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); table_base[(i*2)+1]=period_size_bytes<<16; } @@ -354,8 +262,7 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); - //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes + snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0); snd_emu10k1_ptr20_write(emu, 0x08, channel, 0); @@ -363,41 +270,6 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) return 0; } -/* prepare capture callback */ -static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream) -{ - emu10k1_t *emu = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; - int channel = substream->pcm->device - emu->p16v_device_offset; - u32 tmp; - //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); - switch (runtime->rate) { - case 44100: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800); - break; - case 96000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400); - break; - case 192000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200); - break; - case 48000: - default: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000); - break; - } - /* FIXME: Check emu->buffer.size before actually writing to it. */ - snd_emu10k1_ptr20_write(emu, 0x13, channel, 0); - snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); - snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0); - //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */ - //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<runtime; - emu10k1_pcm_t *epcm = runtime->private_data; - int channel = 0; - int result = 0; - u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_p16v_intr_enable(emu, inte); - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<running = 0; - break; - default: - result = -EINVAL; - break; - } - return result; -} - /* pointer_playback callback */ static snd_pcm_uframes_t snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream) @@ -528,31 +370,6 @@ snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream) return ptr; } -/* pointer_capture callback */ -static snd_pcm_uframes_t -snd_p16v_pcm_pointer_capture(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; - snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; - int channel = 0; - - if (!epcm->running) - return 0; - - ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr=ptr2; - if (ptr >= runtime->buffer_size) { - ptr -= runtime->buffer_size; - printk("buffer capture limited!\n"); - } - //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); - - return ptr; -} - /* operators */ static snd_pcm_ops_t snd_p16v_playback_front_ops = { .open = snd_p16v_pcm_open_playback_front, @@ -565,18 +382,6 @@ static snd_pcm_ops_t snd_p16v_playback_front_ops = { .pointer = snd_p16v_pcm_pointer_playback, }; -static snd_pcm_ops_t snd_p16v_capture_ops = { - .open = snd_p16v_pcm_open_capture, - .close = snd_p16v_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_p16v_pcm_hw_params_capture, - .hw_free = snd_p16v_pcm_hw_free_capture, - .prepare = snd_p16v_pcm_prepare_capture, - .trigger = snd_p16v_pcm_trigger_capture, - .pointer = snd_p16v_pcm_pointer_capture, -}; - - int snd_p16v_free(emu10k1_t *chip) { // release the data @@ -600,22 +405,20 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm) snd_pcm_t *pcm; snd_pcm_substream_t *substream; int err; - int capture=1; + int capture=0; //snd_printk("snd_p16v_pcm called. device=%d\n", device); emu->p16v_device_offset = device; if (rpcm) *rpcm = NULL; - + //if (device == 0) capture=1; if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) return err; pcm->private_data = emu; pcm->private_free = snd_p16v_pcm_free; - // Single playback 8 channel device. - // Single capture 2 channel device. + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops); pcm->info_flags = 0; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; @@ -628,7 +431,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm) if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), - ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) + 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */ return err; //snd_printk("preallocate playback substream: err=%d\n", err); } @@ -639,7 +442,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm) if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), - 65536 - 64, 65536 - 64)) < 0) + 64*1024, 64*1024)) < 0) return err; //snd_printk("preallocate capture substream: err=%d\n", err); } @@ -891,106 +694,6 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear = .put = snd_p16v_volume_put_spdif_rear }; -static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) -{ - static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - emu10k1_t *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->p16v_capture_source; - return 0; -} - -static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - emu10k1_t *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 mask; - u32 source; - - val = ucontrol->value.enumerated.item[0] ; - change = (emu->p16v_capture_source != val); - if (change) { - emu->p16v_capture_source = val; - source = (val << 28) | (val << 24) | (val << 20) | (val << 16); - mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff; - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask); - } - return change; -} - -static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HD Capture source", - .info = snd_p16v_capture_source_info, - .get = snd_p16v_capture_source_get, - .put = snd_p16v_capture_source_put -}; - -static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) -{ - static char *texts[4] = { "0", "1", "2", "3", }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - emu10k1_t *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel; - return 0; -} - -static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - emu10k1_t *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 tmp; - - val = ucontrol->value.enumerated.item[0] ; - change = (emu->p16v_capture_channel != val); - if (change) { - emu->p16v_capture_channel = val; - tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc; - snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val); - } - return change; -} - -static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HD Capture channel", - .info = snd_p16v_capture_channel_info, - .get = snd_p16v_capture_channel_get, - .put = snd_p16v_capture_channel_put -}; - int snd_p16v_mixer(emu10k1_t *emu) { int err; @@ -1028,14 +731,6 @@ int snd_p16v_mixer(emu10k1_t *emu) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; - if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; return 0; } diff --git a/trunk/sound/pci/ens1370.c b/trunk/sound/pci/ens1370.c index 4e63498a58b2..f910399db5c3 100644 --- a/trunk/sound/pci/ens1370.c +++ b/trunk/sound/pci/ens1370.c @@ -2401,7 +2401,7 @@ static struct pci_driver driver = { static int __init alsa_card_ens137x_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_ens137x_exit(void) diff --git a/trunk/sound/pci/es1938.c b/trunk/sound/pci/es1938.c index b492777bc30f..b4ca8adf393c 100644 --- a/trunk/sound/pci/es1938.c +++ b/trunk/sound/pci/es1938.c @@ -1761,7 +1761,7 @@ static struct pci_driver driver = { static int __init alsa_card_es1938_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_es1938_exit(void) diff --git a/trunk/sound/pci/es1968.c b/trunk/sound/pci/es1968.c index ea889b311390..faf63ff19c42 100644 --- a/trunk/sound/pci/es1968.c +++ b/trunk/sound/pci/es1968.c @@ -2559,7 +2559,6 @@ static struct ess_device_list pm_whitelist[] __devinitdata = { { TYPE_MAESTRO2E, 0x103c }, { TYPE_MAESTRO2E, 0x1179 }, { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ - { TYPE_MAESTRO2E, 0x1558 }, }; static struct ess_device_list mpu_blacklist[] __devinitdata = { @@ -2796,7 +2795,7 @@ static struct pci_driver driver = { static int __init alsa_card_es1968_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_es1968_exit(void) diff --git a/trunk/sound/pci/fm801.c b/trunk/sound/pci/fm801.c index ff10e637a95e..08e7c5a296d5 100644 --- a/trunk/sound/pci/fm801.c +++ b/trunk/sound/pci/fm801.c @@ -195,7 +195,6 @@ struct _snd_fm801 { static struct pci_device_id snd_fm801_ids[] = { { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ - { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ { 0, } }; @@ -1469,7 +1468,7 @@ static struct pci_driver driver = { static int __init alsa_card_fm801_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_fm801_exit(void) diff --git a/trunk/sound/pci/hda/Makefile b/trunk/sound/pci/hda/Makefile index bd8cb33c4fb4..570a59d33b41 100644 --- a/trunk/sound/pci/hda/Makefile +++ b/trunk/sound/pci/hda/Makefile @@ -1,5 +1,5 @@ snd-hda-intel-objs := hda_intel.o -snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o +snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o ifdef CONFIG_PROC_FS snd-hda-codec-objs += hda_proc.o endif diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index e2cf02387289..9ed117ac0c09 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -49,10 +49,8 @@ struct hda_vendor_id { /* codec vendor labels */ static struct hda_vendor_id hda_vendor_ids[] = { { 0x10ec, "Realtek" }, - { 0x11d4, "Analog Devices" }, { 0x13f6, "C-Media" }, { 0x434d, "C-Media" }, - { 0x8384, "SigmaTel" }, {} /* terminator */ }; @@ -510,7 +508,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, /* FIXME: support for multiple AFGs? */ codec->afg = look_for_afg_node(codec); if (! codec->afg) { - snd_printdd("hda_codec: no AFG node found\n"); + snd_printk(KERN_ERR "hda_codec: no AFG node found\n"); snd_hda_codec_free(codec); return -ENODEV; } @@ -550,9 +548,6 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, int channel_id, int format) { - if (! nid) - return; - 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, @@ -566,10 +561,9 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre * amp access functions */ -/* FIXME: more better hash key? */ -#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) +#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64) #define INFO_AMP_CAPS (1<<0) -#define INFO_AMP_VOL(ch) (1 << (1 + (ch))) +#define INFO_AMP_VOL (1<<1) /* initialize the hash table */ static void init_amp_hash(struct hda_codec *codec) @@ -628,29 +622,28 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) /* * read the current volume to info - * if the cache exists, read the cache value. + * if the cache exists, read from the cache. */ -static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, +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 info->vol[ch]; + 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); - return info->vol[ch]; + info->status |= INFO_AMP_VOL << ch; } /* - * write the current volume in info to the h/w and update the cache + * write the current volume in info to the h/w */ -static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, +static void put_vol_mute(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index, int val) { u32 parm; @@ -660,34 +653,30 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, parm |= index << AC_AMP_SET_INDEX_SHIFT; parm |= val; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); - info->vol[ch] = val; } /* - * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. + * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. */ -static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) +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; - return get_vol_mute(codec, info, nid, ch, direction, index); + get_vol_mute(codec, info, nid, ch, direction, index); + return info->vol[ch]; } -/* - * update the AMP value, mask = bit mask to set, val = the value - */ -static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val) +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; - val &= mask; - val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; + get_vol_mute(codec, info, nid, ch, direction, idx); if (info->vol[ch] == val && ! codec->in_resume) return 0; - put_vol_mute(codec, info, nid, ch, direction, idx, val); + put_vol_mute(codec, nid, ch, direction, idx, val); + info->vol[ch] = val; return 1; } @@ -746,15 +735,21 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t 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) - change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, - 0x7f, *valp); - if (chs & 2) - change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, - 0x7f, valp[1]); + 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; } @@ -793,15 +788,21 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t 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) - change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, - 0x80, *valp ? 0 : 0x80); - if (chs & 2) - change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, - 0x80, valp[1] ? 0 : 0x80); + 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; } @@ -1447,6 +1448,10 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream 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; @@ -1520,12 +1525,12 @@ int snd_hda_build_pcms(struct hda_bus *bus) * * If no entries are matching, the function returns a negative value. */ -int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl) +int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl) { - const struct hda_board_config *c; + struct hda_board_config *c; if (codec->bus->modelname) { - for (c = tbl; c->modelname || c->pci_subvendor; c++) { + 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); @@ -1538,10 +1543,9 @@ int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_c 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_subvendor; c++) { - if (c->pci_subvendor == subsystem_vendor && - (! c->pci_subdevice /* all match */|| - (c->pci_subdevice == 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; } } @@ -1683,12 +1687,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* surrounds */ for (i = 1; i < mout->num_dacs; i++) { - if (chs >= (i + 1) * 2) /* independent out */ + 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); - else /* copy front */ - snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, - format); } return 0; } @@ -1714,105 +1717,6 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o return 0; } -/* - * Helper for automatic ping configuration - */ -/* parse all pin widgets and store the useful pin nids to cfg */ -int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg) -{ - hda_nid_t nid, nid_start; - int i, j, nodes; - short seq, sequences[4], assoc_line_out; - - memset(cfg, 0, sizeof(*cfg)); - - memset(sequences, 0, sizeof(sequences)); - assoc_line_out = 0; - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); - for (nid = nid_start; nid < nodes + nid_start; 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; - unsigned int def_conf; - short assoc, loc; - - /* read all default configuration for pin complex */ - if (wid_type != AC_WID_PIN) - continue; - def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) - continue; - loc = get_defcfg_location(def_conf); - switch (get_defcfg_device(def_conf)) { - case AC_JACK_LINE_OUT: - case AC_JACK_SPEAKER: - seq = get_defcfg_sequence(def_conf); - assoc = get_defcfg_association(def_conf); - if (! assoc) - continue; - if (! assoc_line_out) - assoc_line_out = assoc; - else if (assoc_line_out != assoc) - continue; - if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) - continue; - cfg->line_out_pins[cfg->line_outs] = nid; - sequences[cfg->line_outs] = seq; - cfg->line_outs++; - break; - case AC_JACK_HP_OUT: - cfg->hp_pin = nid; - break; - case AC_JACK_MIC_IN: - if (loc == AC_JACK_LOC_FRONT) - cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; - else - cfg->input_pins[AUTO_PIN_MIC] = nid; - break; - case AC_JACK_LINE_IN: - if (loc == AC_JACK_LOC_FRONT) - cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; - else - cfg->input_pins[AUTO_PIN_LINE] = nid; - break; - case AC_JACK_CD: - cfg->input_pins[AUTO_PIN_CD] = nid; - break; - case AC_JACK_AUX: - cfg->input_pins[AUTO_PIN_AUX] = nid; - break; - case AC_JACK_SPDIF_OUT: - cfg->dig_out_pin = nid; - break; - case AC_JACK_SPDIF_IN: - cfg->dig_in_pin = nid; - break; - } - } - - /* sort by sequence */ - for (i = 0; i < cfg->line_outs; i++) - for (j = i + 1; j < cfg->line_outs; j++) - if (sequences[i] > sequences[j]) { - seq = sequences[i]; - sequences[i] = sequences[j]; - sequences[j] = seq; - nid = cfg->line_out_pins[i]; - cfg->line_out_pins[i] = cfg->line_out_pins[j]; - cfg->line_out_pins[j] = nid; - } - - /* Swap surround and CLFE: the association order is front/CLFE/surr/back */ - if (cfg->line_outs >= 3) { - nid = cfg->line_out_pins[1]; - cfg->line_out_pins[1] = cfg->line_out_pins[2]; - cfg->line_out_pins[2] = nid; - } - - return 0; -} - #ifdef CONFIG_PM /* * power management diff --git a/trunk/sound/pci/hda/hda_codec.h b/trunk/sound/pci/hda/hda_codec.h index 59991560d492..c9e9dc9c7c98 100644 --- a/trunk/sound/pci/hda/hda_codec.h +++ b/trunk/sound/pci/hda/hda_codec.h @@ -75,9 +75,6 @@ enum { #define AC_VERB_GET_DIGI_CONVERT 0x0f0d #define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f /* f10-f1a: GPIO */ -#define AC_VERB_GET_GPIO_DATA 0x0f15 -#define AC_VERB_GET_GPIO_MASK 0x0f16 -#define AC_VERB_GET_GPIO_DIRECTION 0x0f17 #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c /* @@ -100,9 +97,6 @@ enum { #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_GPIO_DATA 0x715 -#define AC_VERB_SET_GPIO_MASK 0x716 -#define AC_VERB_SET_GPIO_DIRECTION 0x717 #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 @@ -182,15 +176,16 @@ enum { #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 (0x37<<8) +#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) */ -#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ -#define AC_PINCAP_VREF_50 (1<<1) /* 50% */ -#define AC_PINCAP_VREF_GRD (1<<2) /* ground */ -#define AC_PINCAP_VREF_80 (1<<4) /* 80% */ -#define AC_PINCAP_VREF_100 (1<<5) /* 100% */ +/* 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 */ @@ -253,11 +248,6 @@ enum { /* Pin widget control - 8bit */ #define AC_PINCTL_VREFEN (0x7<<0) -#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ -#define AC_PINCTL_VREF_50 1 /* 50% */ -#define AC_PINCTL_VREF_GRD 2 /* ground */ -#define AC_PINCTL_VREF_80 4 /* 80% */ -#define AC_PINCTL_VREF_100 5 /* 100% */ #define AC_PINCTL_IN_EN (1<<5) #define AC_PINCTL_OUT_EN (1<<6) #define AC_PINCTL_HP_EN (1<<7) @@ -265,9 +255,7 @@ enum { /* configuration default - 32bit */ #define AC_DEFCFG_SEQUENCE (0xf<<0) #define AC_DEFCFG_DEF_ASSOC (0xf<<4) -#define AC_DEFCFG_ASSOC_SHIFT 4 #define AC_DEFCFG_MISC (0xf<<8) -#define AC_DEFCFG_MISC_SHIFT 8 #define AC_DEFCFG_COLOR (0xf<<12) #define AC_DEFCFG_COLOR_SHIFT 12 #define AC_DEFCFG_CONN_TYPE (0xf<<16) @@ -425,7 +413,7 @@ struct hda_bus { /* codec linked list */ struct list_head codec_list; - struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ + struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */ struct semaphore cmd_mutex; diff --git a/trunk/sound/pci/hda/hda_generic.c b/trunk/sound/pci/hda/hda_generic.c index 2d046abb5911..69f7b6c4cf83 100644 --- a/trunk/sound/pci/hda/hda_generic.c +++ b/trunk/sound/pci/hda/hda_generic.c @@ -44,7 +44,7 @@ struct hda_gnode { struct list_head list; }; -/* patch-specific record */ +/* pathc-specific record */ struct hda_gspec { struct hda_gnode *dac_node; /* DAC node */ struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */ @@ -68,8 +68,8 @@ struct hda_gspec { /* * retrieve the default device type from the default config value */ -#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) -#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) +#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 @@ -323,7 +323,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, if (! (node->pin_caps & AC_PINCAP_OUT)) continue; if (jack_type >= 0) { - if (jack_type != defcfg_type(node)) + if (jack_type != get_defcfg_type(node)) continue; if (node->wid_caps & AC_WCAP_DIGITAL) continue; /* skip SPDIF */ @@ -418,15 +418,15 @@ static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc */ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) { - unsigned int location = defcfg_location(node); - switch (defcfg_type(node)) { + 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_PINCTL_VREF_GRD; + *pinctl |= AC_PIN_VREF_GRD; return "CD"; case AC_JACK_AUX: if ((location & 0x0f) == AC_JACK_LOC_FRONT) diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 5e0cca36ed57..959953ca320a 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -51,7 +51,6 @@ 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]; -static int position_fix[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -61,17 +60,12 @@ 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_param_array(position_fix, int, NULL, 0444); -MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)."); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH6M}," "{Intel, ICH7}," - "{Intel, ESB2}," - "{ATI, SB450}," - "{VIA, VT8251}," - "{VIA, VT8237A}}"); + "{Intel, ESB2}}"); MODULE_DESCRIPTION("Intel HDA driver"); #define SFX "hda-intel: " @@ -156,7 +150,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* STATESTS int mask: SD2,SD1,SD0 */ #define STATESTS_INT_MASK 0x07 -#define AZX_MAX_CODECS 4 +#define AZX_MAX_CODECS 3 /* SD_CTL bits */ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ @@ -189,18 +183,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define ICH6_MAX_CORB_ENTRIES 256 #define ICH6_MAX_RIRB_ENTRIES 256 -/* position fix mode */ -enum { - POS_FIX_FIFO, - POS_FIX_NONE, - POS_FIX_POSBUF -}; - -/* Defines for ATI HD Audio support in SB450 south bridge */ -#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b -#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 -#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 - /* * Use CORB/RIRB for communication from/to codecs. @@ -208,6 +190,12 @@ enum { */ #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 */ + /* */ @@ -283,10 +271,6 @@ struct snd_azx { struct snd_dma_buffer bdl; struct snd_dma_buffer rb; struct snd_dma_buffer posbuf; - - /* flags */ - int position_fix; - unsigned int initialized: 1; }; /* @@ -654,7 +638,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev) */ static void azx_init_chip(azx_t *chip) { - unsigned char tcsel_reg, ati_misc_cntl2; + 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 @@ -673,20 +657,11 @@ static void azx_init_chip(azx_t *chip) /* initialize the codec command I/O */ azx_init_cmd_io(chip); - if (chip->position_fix == POS_FIX_POSBUF) { - /* program the position buffer */ - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); - azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); - } - - /* For ATI SB450 azalia HD audio, we need to enable snoop */ - if (chip->pci->vendor == PCI_VENDOR_ID_ATI && - chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) { - pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, - &ati_misc_cntl2); - pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, - (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); - } +#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 } @@ -816,12 +791,11 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev) /* upper BDL address */ azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); - if (chip->position_fix == POS_FIX_POSBUF) { - /* enable the position buffer */ - if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); - } - +#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); @@ -1062,20 +1036,16 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) static snd_pcm_uframes_t azx_pcm_pointer(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); unsigned int pos; - if (chip->position_fix == POS_FIX_POSBUF) { - /* use the position buffer */ - pos = *azx_dev->posbuf; - } else { - /* read LPIB */ - pos = azx_sd_readl(azx_dev, SD_LPIB); - if (chip->position_fix == POS_FIX_FIFO) - pos += azx_dev->fifo_size; - } +#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); @@ -1185,8 +1155,9 @@ static int __devinit azx_init_stream(azx_t *chip) 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; - if (chip->position_fix == POS_FIX_POSBUF) - azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); +#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 */ @@ -1236,7 +1207,7 @@ static int azx_resume(snd_card_t *card) */ static int azx_free(azx_t *chip) { - if (chip->initialized) { + if (chip->remap_addr) { int i; for (i = 0; i < MAX_ICH6_DEV; i++) @@ -1266,8 +1237,10 @@ static int azx_free(azx_t *chip) 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); @@ -1283,8 +1256,7 @@ static int azx_dev_free(snd_device_t *device) /* * constructor */ -static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, - int posfix, azx_t **rchip) +static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip) { azx_t *chip; int err = 0; @@ -1311,8 +1283,6 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; - chip->position_fix = posfix; - if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { kfree(chip); pci_disable_device(pci); @@ -1344,14 +1314,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); goto errout; } - if (chip->position_fix == POS_FIX_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; - } +#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; @@ -1362,8 +1332,6 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, /* initialize chip */ azx_init_chip(chip); - chip->initialized = 1; - /* codec detection */ if (! chip->codec_mask) { snd_printk(KERN_ERR SFX "no codecs found!\n"); @@ -1404,7 +1372,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * return -ENOMEM; } - if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) { + if ((err = azx_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; } @@ -1456,9 +1424,6 @@ 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 */ { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */ - { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */ - { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */ - { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */ { 0, } }; MODULE_DEVICE_TABLE(pci, azx_ids); @@ -1474,7 +1439,7 @@ static struct pci_driver driver = { static int __init alsa_card_azx_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_azx_exit(void) diff --git a/trunk/sound/pci/hda/hda_local.h b/trunk/sound/pci/hda/hda_local.h index 810cfd2d9bba..7c7b849875a0 100644 --- a/trunk/sound/pci/hda/hda_local.h +++ b/trunk/sound/pci/hda/hda_local.h @@ -126,11 +126,11 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } struct hda_board_config { const char *modelname; int config; - unsigned short pci_subvendor; - unsigned short pci_subdevice; + unsigned short pci_vendor; + unsigned short pci_device; }; -int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl); +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); /* @@ -158,35 +158,4 @@ struct hda_bus_unsolicited { struct work_struct work; }; -/* - * Helper for automatic ping configuration - */ - -enum { - AUTO_PIN_MIC, - AUTO_PIN_FRONT_MIC, - AUTO_PIN_LINE, - AUTO_PIN_FRONT_LINE, - AUTO_PIN_CD, - AUTO_PIN_AUX, - AUTO_PIN_LAST -}; - -struct auto_pin_cfg { - int line_outs; - hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */ - hda_nid_t hp_pin; - hda_nid_t input_pins[AUTO_PIN_LAST]; - hda_nid_t dig_out_pin; - hda_nid_t dig_in_pin; -}; - -#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) -#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) -#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) -#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE) -#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) - -int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg); - #endif /* __SOUND_HDA_LOCAL_H */ diff --git a/trunk/sound/pci/hda/hda_patch.h b/trunk/sound/pci/hda/hda_patch.h index a5de684b6944..cf6abce42bc9 100644 --- a/trunk/sound/pci/hda/hda_patch.h +++ b/trunk/sound/pci/hda/hda_patch.h @@ -8,13 +8,10 @@ extern struct hda_codec_preset snd_hda_preset_realtek[]; extern struct hda_codec_preset snd_hda_preset_cmedia[]; /* Analog Devices codecs */ extern struct hda_codec_preset snd_hda_preset_analog[]; -/* SigmaTel codecs */ -extern struct hda_codec_preset snd_hda_preset_sigmatel[]; static const struct hda_codec_preset *hda_preset_tables[] = { snd_hda_preset_realtek, snd_hda_preset_cmedia, snd_hda_preset_analog, - snd_hda_preset_sigmatel, NULL }; diff --git a/trunk/sound/pci/hda/hda_proc.c b/trunk/sound/pci/hda/hda_proc.c index de1217bd8e68..4d5db7faad8d 100644 --- a/trunk/sound/pci/hda/hda_proc.c +++ b/trunk/sound/pci/hda/hda_proc.c @@ -68,27 +68,21 @@ static void print_amp_caps(snd_info_buffer_t *buffer, static void print_amp_vals(snd_info_buffer_t *buffer, struct hda_codec *codec, hda_nid_t nid, - int dir, int stereo, int indices) + int dir, int stereo) { unsigned int val; - int i; - - if (dir == HDA_OUTPUT) - dir = AC_AMP_GET_OUTPUT; - else - dir = AC_AMP_GET_INPUT; - for (i = 0; i < indices; i++) { - snd_iprintf(buffer, " ["); - if (stereo) { - val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_LEFT | dir | i); - snd_iprintf(buffer, "0x%02x ", val); - } + if (stereo) { val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_RIGHT | dir | i); - snd_iprintf(buffer, "0x%02x]", val); + AC_AMP_GET_LEFT | + (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : + AC_AMP_GET_INPUT)); + snd_iprintf(buffer, "0x%02x ", val); } - snd_iprintf(buffer, "\n"); + 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, @@ -163,7 +157,6 @@ static const char *get_jack_color(u32 cfg) static void print_pin_caps(snd_info_buffer_t *buffer, struct hda_codec *codec, hda_nid_t nid) { - static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; static char *jack_types[16] = { "Line Out", "Speaker", "HP Out", "CD", "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", @@ -183,8 +176,7 @@ static void print_pin_caps(snd_info_buffer_t *buffer, 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] %s at %s %s\n", caps, - jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], + 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)); @@ -223,9 +215,6 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) 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; - int conn_len = 0; - hda_nid_t conn[HDA_MAX_CONNECTIONS]; - 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) @@ -240,23 +229,19 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) snd_iprintf(buffer, " Amp-Out"); snd_iprintf(buffer, "\n"); - if (wid_caps & AC_WCAP_CONN_LIST) - conn_len = snd_hda_get_connections(codec, nid, conn, - HDA_MAX_CONNECTIONS); - 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, conn_len); + 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, 1); + wid_caps & AC_WCAP_STEREO); } if (wid_type == AC_WID_PIN) { @@ -280,17 +265,14 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) } if (wid_caps & AC_WCAP_CONN_LIST) { - int c, curr = -1; - if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) - curr = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONNECT_SEL, 0); + 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++) { + for (c = 0; c < conn_len; c++) snd_iprintf(buffer, " 0x%02x", conn[c]); - if (c == curr) - snd_iprintf(buffer, "*"); - } snd_iprintf(buffer, "\n"); } } diff --git a/trunk/sound/pci/hda/patch_analog.c b/trunk/sound/pci/hda/patch_analog.c index 2fd05bb84136..75d23849f71a 100644 --- a/trunk/sound/pci/hda/patch_analog.c +++ b/trunk/sound/pci/hda/patch_analog.c @@ -1,5 +1,5 @@ /* - * HD audio interface patch for AD1981HD, AD1983, AD1986A + * HD audio interface patch for AD1986A * * Copyright (c) 2005 Takashi Iwai * @@ -27,239 +27,13 @@ #include "hda_codec.h" #include "hda_local.h" -struct ad198x_spec { +struct ad1986a_spec { struct semaphore amp_mutex; /* PCM volume/mute control mutex */ struct hda_multi_out multiout; /* playback */ - hda_nid_t adc_nid; - const struct hda_input_mux *input_mux; unsigned int cur_mux; /* capture source */ - unsigned int spdif_route; - snd_kcontrol_new_t *mixers; - const struct hda_verb *init_verbs; struct hda_pcm pcm_rec[2]; /* PCM information */ }; -/* - * input MUX handling (common part) - */ -static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - return snd_hda_input_mux_info(spec->input_mux, uinfo); -} - -static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->cur_mux; - return 0; -} - -static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->adc_nid, &spec->cur_mux); -} - -/* - * initialization (common callbacks) - */ -static int ad198x_init(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - snd_hda_sequence_write(codec, spec->init_verbs); - return 0; -} - -static int ad198x_build_controls(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - int err; - - err = snd_hda_add_new_ctls(codec, spec->mixers); - 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; - return 0; -} - -/* - * Analog playback callbacks - */ -static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); -} - -static int ad198x_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 ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital out - */ -static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -/* - * Analog capture - */ -static int ad198x_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 ad198x_spec *spec = codec->spec; - snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format); - return 0; -} - -static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct ad198x_spec *spec = codec->spec; - snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0); - return 0; -} - - -/* - */ -static struct hda_pcm_stream ad198x_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 6, - .nid = 0, /* fill later */ - .ops = { - .open = ad198x_playback_pcm_open, - .prepare = ad198x_playback_pcm_prepare, - .cleanup = ad198x_playback_pcm_cleanup - }, -}; - -static struct hda_pcm_stream ad198x_pcm_analog_capture = { - .substreams = 2, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .prepare = ad198x_capture_pcm_prepare, - .cleanup = ad198x_capture_pcm_cleanup - }, -}; - -static struct hda_pcm_stream ad198x_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .open = ad198x_dig_playback_pcm_open, - .close = ad198x_dig_playback_pcm_close - }, -}; - -static int ad198x_build_pcms(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "AD198x Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid; - - if (spec->multiout.dig_out_nid) { - info++; - codec->num_pcms++; - info->name = "AD198x Digital"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; - } - - return 0; -} - -static void ad198x_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} - -#ifdef CONFIG_PM -static int ad198x_resume(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - - ad198x_init(codec); - snd_hda_resume_ctls(codec, spec->mixers); - snd_hda_resume_spdif_out(codec); - return 0; -} -#endif - -static struct hda_codec_ops ad198x_patch_ops = { - .build_controls = ad198x_build_controls, - .build_pcms = ad198x_build_pcms, - .init = ad198x_init, - .free = ad198x_free, -#ifdef CONFIG_PM - .resume = ad198x_resume, -#endif -}; - - -/* - * AD1986A specific - */ - #define AD1986A_SPDIF_OUT 0x02 #define AD1986A_FRONT_DAC 0x03 #define AD1986A_SURR_DAC 0x04 @@ -294,7 +68,7 @@ static struct hda_input_mux ad1986a_capture_source = { static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *ad = codec->spec; + struct ad1986a_spec *ad = codec->spec; down(&ad->amp_mutex); snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); @@ -305,7 +79,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *ad = codec->spec; + struct ad1986a_spec *ad = codec->spec; int i, change = 0; down(&ad->amp_mutex); @@ -318,12 +92,12 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ return change; } -#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info +#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *ad = codec->spec; + struct ad1986a_spec *ad = codec->spec; down(&ad->amp_mutex); snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); @@ -334,7 +108,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *ad = codec->spec; + struct ad1986a_spec *ad = codec->spec; int i, change = 0; down(&ad->amp_mutex); @@ -347,6 +121,32 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t return change; } +/* + * input MUX handling + */ +static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo); +} + +static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct ad1986a_spec *spec = codec->spec; + + ucontrol->value.enumerated.item[0] = spec->cur_mux; + return 0; +} + +static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct ad1986a_spec *spec = codec->spec; + + return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol, + AD1986A_ADC, &spec->cur_mux); +} + /* * mixers */ @@ -394,9 +194,9 @@ static snd_kcontrol_new_t ad1986a_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, + .info = ad1986a_mux_enum_info, + .get = ad1986a_mux_enum_get, + .put = ad1986a_mux_enum_put, }, HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), { } /* end */ @@ -441,328 +241,183 @@ static struct hda_verb ad1986a_init_verbs[] = { {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* HP Pin */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, - /* Front, Surround, CLFE Pins */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Mono Pin */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Mic Pin */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* Line, Aux, CD, Beep-In Pin */ - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, { } /* end */ }; -static int patch_ad1986a(struct hda_codec *codec) +static int ad1986a_init(struct hda_codec *codec) { - struct ad198x_spec *spec; - - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - init_MUTEX(&spec->amp_mutex); - codec->spec = spec; - - spec->multiout.max_channels = 6; - spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); - spec->multiout.dac_nids = ad1986a_dac_nids; - spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; - spec->adc_nid = AD1986A_ADC; - spec->input_mux = &ad1986a_capture_source; - spec->mixers = ad1986a_mixers; - spec->init_verbs = ad1986a_init_verbs; + snd_hda_sequence_write(codec, ad1986a_init_verbs); + return 0; +} - codec->patch_ops = ad198x_patch_ops; +static int ad1986a_build_controls(struct hda_codec *codec) +{ + int err; + err = snd_hda_add_new_ctls(codec, ad1986a_mixers); + if (err < 0) + return err; + err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT); + if (err < 0) + return err; return 0; } /* - * AD1983 specific + * Analog playback callbacks */ +static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct ad1986a_spec *spec = codec->spec; + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); +} -#define AD1983_SPDIF_OUT 0x02 -#define AD1983_DAC 0x03 -#define AD1983_ADC 0x04 - -static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; +static int ad1986a_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 ad1986a_spec *spec = codec->spec; + return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} -static struct hda_input_mux ad1983_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Line", 0x1 }, - { "Mix", 0x2 }, - { "Mix Mono", 0x3 }, - }, -}; +static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) +{ + struct ad1986a_spec *spec = codec->spec; + return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); +} /* - * SPDIF playback route + * Digital out */ -static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) { - static char *texts[] = { "PCM", "ADC" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; + struct ad1986a_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); } -static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) { - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; + struct ad1986a_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); +} - ucontrol->value.enumerated.item[0] = spec->spdif_route; +/* + * Analog capture + */ +static int ad1986a_capture_pcm_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, AD1986A_ADC, stream_tag, 0, format); return 0; } -static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) { - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { - spec->spdif_route = ucontrol->value.enumerated.item[0]; - snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0, - AC_VERB_SET_CONNECT_SEL, spec->spdif_route); - return 1; - } + snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0); return 0; } -static snd_kcontrol_new_t ad1983_mixers[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, + +/* + */ +static struct hda_pcm_stream ad1986a_pcm_analog_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 6, + .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */ + .ops = { + .open = ad1986a_playback_pcm_open, + .prepare = ad1986a_playback_pcm_prepare, + .cleanup = ad1986a_playback_pcm_cleanup }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Playback Route", - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, +}; + +static struct hda_pcm_stream ad1986a_pcm_analog_capture = { + .substreams = 2, + .channels_min = 2, + .channels_max = 2, + .nid = AD1986A_ADC, /* NID to query formats and rates */ + .ops = { + .prepare = ad1986a_capture_pcm_prepare, + .cleanup = ad1986a_capture_pcm_cleanup }, - { } /* end */ }; -static struct hda_verb ad1983_init_verbs[] = { - /* Front, HP, Mono; mute as default */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Beep, PCM, Mic, Line-In: mute */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Front, HP selectors; from Mix */ - {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* Mono selector; from Mix */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic selector; Mic */ - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Line-in selector: Line-in */ - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Mic boost: 0dB */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* Record selector: mic */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* SPDIF route: PCM */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Front Pin */ - {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* HP Pin */ - {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, - /* Mono Pin */ - {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Mic Pin */ - {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* Line Pin */ - {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - { } /* end */ +static struct hda_pcm_stream ad1986a_pcm_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = AD1986A_SPDIF_OUT, + .ops = { + .open = ad1986a_dig_playback_pcm_open, + .close = ad1986a_dig_playback_pcm_close + }, }; -static int patch_ad1983(struct hda_codec *codec) +static int ad1986a_build_pcms(struct hda_codec *codec) { - struct ad198x_spec *spec; - - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + struct ad1986a_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; - init_MUTEX(&spec->amp_mutex); - codec->spec = spec; + codec->num_pcms = 2; + codec->pcm_info = info; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); - spec->multiout.dac_nids = ad1983_dac_nids; - spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; - spec->adc_nid = AD1983_ADC; - spec->input_mux = &ad1983_capture_source; - spec->mixers = ad1983_mixers; - spec->init_verbs = ad1983_init_verbs; - spec->spdif_route = 0; + info->name = "AD1986A Analog"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback; + info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture; + info++; - codec->patch_ops = ad198x_patch_ops; + info->name = "AD1986A Digital"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback; return 0; } +static void ad1986a_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} -/* - * AD1981 HD specific - */ - -#define AD1981_SPDIF_OUT 0x02 -#define AD1981_DAC 0x03 -#define AD1981_ADC 0x04 - -static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; - -/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ -static struct hda_input_mux ad1981_capture_source = { - .num_items = 7, - .items = { - { "Front Mic", 0x0 }, - { "Line", 0x1 }, - { "Mix", 0x2 }, - { "Mix Mono", 0x3 }, - { "CD", 0x4 }, - { "Mic", 0x6 }, - { "Aux", 0x7 }, - }, -}; - -static snd_kcontrol_new_t ad1981_mixers[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* identical with AD1983 */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Playback Route", - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; +#ifdef CONFIG_PM +static int ad1986a_resume(struct hda_codec *codec) +{ + ad1986a_init(codec); + snd_hda_resume_ctls(codec, ad1986a_mixers); + snd_hda_resume_spdif_out(codec); + return 0; +} +#endif -static struct hda_verb ad1981_init_verbs[] = { - /* Front, HP, Mono; mute as default */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Front, HP selectors; from Mix */ - {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* Mono selector; from Mix */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic Mixer; select Front Mic */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Mic boost: 0dB */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* Record selector: Front mic */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* SPDIF route: PCM */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Front Pin */ - {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* HP Pin */ - {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, - /* Mono Pin */ - {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Front & Rear Mic Pins */ - {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* Line Pin */ - {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - /* Digital Beep */ - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Line-Out as Input: disabled */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - { } /* end */ +static struct hda_codec_ops ad1986a_patch_ops = { + .build_controls = ad1986a_build_controls, + .build_pcms = ad1986a_build_pcms, + .init = ad1986a_init, + .free = ad1986a_free, +#ifdef CONFIG_PM + .resume = ad1986a_resume, +#endif }; -static int patch_ad1981(struct hda_codec *codec) +static int patch_ad1986a(struct hda_codec *codec) { - struct ad198x_spec *spec; + struct ad1986a_spec *spec; spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -771,28 +426,20 @@ static int patch_ad1981(struct hda_codec *codec) init_MUTEX(&spec->amp_mutex); codec->spec = spec; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); - spec->multiout.dac_nids = ad1981_dac_nids; - spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; - spec->adc_nid = AD1981_ADC; - spec->input_mux = &ad1981_capture_source; - spec->mixers = ad1981_mixers; - spec->init_verbs = ad1981_init_verbs; - spec->spdif_route = 0; + spec->multiout.max_channels = 6; + spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); + spec->multiout.dac_nids = ad1986a_dac_nids; + spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; - codec->patch_ops = ad198x_patch_ops; + codec->patch_ops = ad1986a_patch_ops; return 0; } - /* * patch entries */ struct hda_codec_preset snd_hda_preset_analog[] = { - { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, - { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, {} /* terminator */ }; diff --git a/trunk/sound/pci/hda/patch_cmedia.c b/trunk/sound/pci/hda/patch_cmedia.c index 2d6e3e3d0a38..b7cc8e4bffb7 100644 --- a/trunk/sound/pci/hda/patch_cmedia.c +++ b/trunk/sound/pci/hda/patch_cmedia.c @@ -29,7 +29,6 @@ #include #include "hda_codec.h" #include "hda_local.h" -#define NUM_PINS 11 /* board config type */ @@ -39,7 +38,6 @@ enum { 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 */ - CMI_AUTO, /* let driver guess it */ }; struct cmi_spec { @@ -50,8 +48,6 @@ struct cmi_spec { /* playback */ struct hda_multi_out multiout; - hda_nid_t dac_nids[4]; /* NID for each DAC */ - int num_dacs; /* capture */ hda_nid_t *adc_nids; @@ -67,30 +63,8 @@ struct cmi_spec { const struct cmi_channel_mode *channel_modes; struct hda_pcm pcm_rec[2]; /* PCM information */ - - /* pin deafault configuration */ - hda_nid_t pin_nid[NUM_PINS]; - unsigned int def_conf[NUM_PINS]; - unsigned int pin_def_confs; - - /* multichannel pins */ - hda_nid_t multich_pin[4]; /* max 8-channel */ - struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ }; -/* amp values */ -#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) -#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) -#define AMP_OUT_MUTE 0xb080 -#define AMP_OUT_UNMUTE 0xb000 -#define AMP_OUT_ZERO 0xb000 -/* pinctl values */ -#define PIN_IN 0x20 -#define PIN_VREF80 0x24 -#define PIN_VREF50 0x21 -#define PIN_OUT 0x40 -#define PIN_HP 0xc0 - /* * input MUX */ @@ -128,9 +102,9 @@ static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon /* 3-stack / 2 channel */ static struct hda_verb cmi9880_ch2_init[] = { /* set line-in PIN for input */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, /* set mic PIN for input, also enable vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* route front PCM (DAC1) to HP */ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, {} @@ -139,9 +113,9 @@ static struct hda_verb cmi9880_ch2_init[] = { /* 3-stack / 6 channel */ static struct hda_verb cmi9880_ch6_init[] = { /* set line-in PIN for output */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, /* set mic PIN for output */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, /* route front PCM (DAC1) to HP */ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, {} @@ -150,9 +124,9 @@ static struct hda_verb cmi9880_ch6_init[] = { /* 3-stack+front / 8 channel */ static struct hda_verb cmi9880_ch8_init[] = { /* set line-in PIN for output */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, /* set mic PIN for output */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, /* route rear-surround PCM (DAC4) to HP */ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, {} @@ -295,27 +269,25 @@ static hda_nid_t cmi9880_adc_nids[2] = { */ static struct hda_verb cmi9880_basic_init[] = { /* port-D for line out (rear panel) */ - { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, + { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, + { 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, PIN_HP }, + { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-G for CLFE (rear panel) */ - { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, + { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-H for side (rear panel) */ - { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-C for line-in (rear panel) */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, /* port-B for mic-in (rear panel) with vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* port-F for mic-in (front panel) with vref */ - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* CD-in */ - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_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 }, @@ -324,27 +296,23 @@ static struct hda_verb cmi9880_basic_init[] = { static struct hda_verb cmi9880_allout_init[] = { /* port-D for line out (rear panel) */ - { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, + { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, + { 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, PIN_HP }, + { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-G for CLFE (rear panel) */ - { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, - /* port-H for side (rear panel) */ - { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-C for surround (rear panel) */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, + { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* port-B for mic-in (rear panel) with vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* port-F for mic-in (front panel) with vref */ - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* CD-in */ - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_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 }, @@ -379,81 +347,6 @@ static int cmi9880_build_controls(struct hda_codec *codec) return 0; } -/* fill in the multi_dac_nids table, which will decide - which audio widget to use for each channel */ -static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) -{ - struct cmi_spec *spec = codec->spec; - hda_nid_t nid; - int assigned[4]; - int i, j; - - /* clear the table, only one c-media dac assumed here */ - memset(spec->dac_nids, 0, sizeof(spec->dac_nids)); - memset(assigned, 0, sizeof(assigned)); - /* check the pins we found */ - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */ - if (nid >= 0x0b && nid <= 0x0e) { - spec->dac_nids[i] = (nid - 0x0b) + 0x03; - assigned[nid - 0x0b] = 1; - } - } - /* left pin can be connect to any audio widget */ - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - if (nid <= 0x0e) - continue; - /* search for an empty channel */ - for (j = 0; j < cfg->line_outs; j++) { - if (! assigned[j]) { - spec->dac_nids[i] = i + 0x03; - assigned[j] = 1; - break; - } - } - } - spec->num_dacs = cfg->line_outs; - return 0; -} - -/* create multi_init table, which is used for multichannel initialization */ -static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg) -{ - struct cmi_spec *spec = codec->spec; - hda_nid_t nid; - int i, j, k, len; - - /* clear the table, only one c-media dac assumed here */ - memset(spec->multi_init, 0, sizeof(spec->multi_init)); - for (j = 0, i = 0; i < cfg->line_outs; i++) { - hda_nid_t conn[4]; - nid = cfg->line_out_pins[i]; - /* set as output */ - spec->multi_init[j].nid = nid; - spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL; - spec->multi_init[j].param = PIN_OUT; - j++; - if (nid > 0x0e) { - /* set connection */ - spec->multi_init[j].nid = nid; - spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL; - spec->multi_init[j].param = 0; - /* find the index in connect list */ - len = snd_hda_get_connections(codec, nid, conn, 4); - for (k = 0; k < len; k++) - if (conn[k] == spec->dac_nids[i]) { - spec->multi_init[j].param = j; - break; - } - j++; - break; - } - } - return 0; -} - static int cmi9880_init(struct hda_codec *codec) { struct cmi_spec *spec = codec->spec; @@ -461,8 +354,6 @@ static int cmi9880_init(struct hda_codec *codec) snd_hda_sequence_write(codec, cmi9880_allout_init); else snd_hda_sequence_write(codec, cmi9880_basic_init); - if (spec->board_config == CMI_AUTO) - snd_hda_sequence_write(codec, spec->multi_init); return 0; } @@ -649,7 +540,6 @@ static struct hda_board_config cmi9880_cfg_tbl[] = { { .modelname = "full", .config = CMI_FULL }, { .modelname = "full_dig", .config = CMI_FULL_DIG }, { .modelname = "allout", .config = CMI_ALLOUT }, - { .modelname = "auto", .config = CMI_AUTO }, {} /* terminator */ }; @@ -674,14 +564,10 @@ static int patch_cmi9880(struct hda_codec *codec) codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); if (spec->board_config < 0) { - snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); - spec->board_config = CMI_AUTO; /* try everything */ + snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); + spec->board_config = CMI_FULL_DIG; /* try everything */ } - /* copy default DAC NIDs */ - memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); - spec->num_dacs = 4; - switch (spec->board_config) { case CMI_MINIMAL: case CMI_MIN_FP: @@ -713,58 +599,10 @@ static int patch_cmi9880(struct hda_codec *codec) spec->input_mux = &cmi9880_no_line_mux; spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; break; - case CMI_AUTO: - { - unsigned int port_e, port_f, port_g, port_h; - unsigned int port_spdifi, port_spdifo; - struct auto_pin_cfg cfg; - - /* collect pin default configuration */ - port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - spec->front_panel = 1; - if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || - get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { - port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - spec->surr_switch = 1; - /* no front panel */ - if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || - get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) { - /* no optional rear panel */ - spec->board_config = CMI_MINIMAL; - spec->front_panel = 0; - spec->num_ch_modes = 2; - } else { - spec->board_config = CMI_MIN_FP; - spec->num_ch_modes = 3; - } - spec->channel_modes = cmi9880_channel_modes; - spec->input_mux = &cmi9880_basic_mux; - spec->multiout.max_channels = cmi9880_channel_modes[0].channels; - } else { - spec->input_mux = &cmi9880_basic_mux; - port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) - spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; - if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) - spec->dig_in_nid = CMI_DIG_IN_NID; - spec->multiout.max_channels = 8; - } - snd_hda_parse_pin_def_config(codec, &cfg); - if (cfg.line_outs) { - spec->multiout.max_channels = cfg.line_outs * 2; - cmi9880_fill_multi_dac_nids(codec, &cfg); - cmi9880_fill_multi_init(codec, &cfg); - } else - snd_printd("patch_cmedia: cannot detect association in defcfg\n"); - break; - } } - spec->multiout.num_dacs = spec->num_dacs; - spec->multiout.dac_nids = spec->dac_nids; + spec->multiout.num_dacs = 4; + spec->multiout.dac_nids = cmi9880_dac_nids; spec->adc_nids = cmi9880_adc_nids; diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 9edd558d6bd3..17c5062423ae 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -33,73 +33,38 @@ /* ALC880 board config type */ enum { + ALC880_MINIMAL, ALC880_3ST, ALC880_3ST_DIG, ALC880_5ST, ALC880_5ST_DIG, ALC880_W810, - ALC880_Z71V, - ALC880_AUTO, - ALC880_6ST_DIG, - ALC880_F1734, - ALC880_ASUS, - ALC880_ASUS_DIG, - ALC880_ASUS_W1V, - ALC880_UNIWILL_DIG, -#ifdef CONFIG_SND_DEBUG - ALC880_TEST, -#endif - ALC880_MODEL_LAST /* last tag */ -}; - -/* ALC260 models */ -enum { - ALC260_BASIC, - ALC260_HP, - ALC260_MODEL_LAST /* last tag */ }; -/* amp values */ -#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) -#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) -#define AMP_OUT_MUTE 0xb080 -#define AMP_OUT_UNMUTE 0xb000 -#define AMP_OUT_ZERO 0xb000 -/* pinctl values */ -#define PIN_IN 0x20 -#define PIN_VREF80 0x24 -#define PIN_VREF50 0x21 -#define PIN_OUT 0x40 -#define PIN_HP 0xc0 - struct alc_spec { /* codec parameterization */ - snd_kcontrol_new_t *mixers[3]; /* mixer arrays */ + unsigned int front_panel: 1; + + snd_kcontrol_new_t* mixers[2]; unsigned int num_mixers; - const struct hda_verb *init_verbs[3]; /* initialization verbs - * don't forget NULL termination! - */ - unsigned int num_init_verbs; + struct hda_verb *init_verbs; - char *stream_name_analog; /* analog PCM stream */ + char* stream_name_analog; struct hda_pcm_stream *stream_analog_playback; struct hda_pcm_stream *stream_analog_capture; - char *stream_name_digital; /* digital PCM stream */ + char* stream_name_digital; struct hda_pcm_stream *stream_digital_playback; struct hda_pcm_stream *stream_digital_capture; /* playback */ - struct hda_multi_out multiout; /* playback set-up - * max_channels, dacs must be set - * dig_out_nid and hp_nid are optional - */ + struct hda_multi_out multiout; /* capture */ unsigned int num_adc_nids; hda_nid_t *adc_nids; - hda_nid_t dig_in_nid; /* digital-in NID; optional */ + hda_nid_t dig_in_nid; /* capture source */ const struct hda_input_mux *input_mux; @@ -110,17 +75,61 @@ struct alc_spec { int num_channel_mode; /* PCM information */ - struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ + 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, +}; - struct semaphore bind_mutex; /* for bound controls */ +#define ALC260_DIGOUT_NID 0x03 +#define ALC260_DIGIN_NID 0x06 - /* dynamic controls, init_verbs and input_mux */ - struct auto_pin_cfg autocfg; - unsigned int num_kctl_alloc, num_kctl_used; - snd_kcontrol_new_t *kctl_alloc; - struct hda_input_mux private_imux; +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 = 4, + .items = { + { "Mic", 0x0 }, + { "Front Mic", 0x1 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; /* * input MUX handling @@ -151,7 +160,6 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); } - /* * channel mode setting */ @@ -160,18 +168,135 @@ struct alc_channel_mode { 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; - int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; snd_assert(spec->channel_mode, return -ENXIO); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; - uinfo->value.enumerated.items = items; - if (uinfo->value.enumerated.item >= items) - uinfo->value.enumerated.item = items - 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; @@ -181,16 +306,10 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; - int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; - int i; snd_assert(spec->channel_mode, return -ENXIO); - for (i = 0; i < items; i++) { - if (spec->multiout.max_channels == spec->channel_mode[i].channels) { - ucontrol->value.enumerated.item[0] = i; - break; - } - } + ucontrol->value.enumerated.item[0] = + (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1; return 0; } @@ -216,149 +335,21 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc /* - * bound volume controls - * - * bind multiple volumes (# indices, from 0) - */ - -#define AMP_VAL_IDX_SHIFT 19 -#define AMP_VAL_IDX_MASK (0x0f<<19) - -static int alc_bind_switch_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; - unsigned long pval; - - down(&spec->bind_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - snd_hda_mixer_amp_switch_info(kcontrol, uinfo); - kcontrol->private_value = pval; - up(&spec->bind_mutex); - return 0; -} - -static int alc_bind_switch_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 long pval; - - down(&spec->bind_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); - kcontrol->private_value = pval; - up(&spec->bind_mutex); - return 0; -} - -static int alc_bind_switch_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 long pval; - int i, indices, change = 0; - - down(&spec->bind_mutex); - pval = kcontrol->private_value; - indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; - for (i = 0; i < indices; i++) { - kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); - change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - } - kcontrol->private_value = pval; - up(&spec->bind_mutex); - return change; -} - -#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = alc_bind_switch_info, \ - .get = alc_bind_switch_get, \ - .put = alc_bind_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } - -#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir) - - -/* - * ALC880 3-stack model - * - * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) - * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b - * HP = 0x19 */ -static hda_nid_t alc880_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x05, 0x04, 0x03 -}; - -static hda_nid_t alc880_adc_nids[3] = { - /* ADC0-2 */ - 0x07, 0x08, 0x09, -}; - -/* The datasheet says the node 0x07 is connected from inputs, - * but it shows zero connection in the real implementation on some devices. +/* 3-stack mode + * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b + * HP=0x19 */ -static hda_nid_t alc880_adc_nids_alt[2] = { - /* ADC1-2 */ - 0x08, 0x09, -}; - -#define ALC880_DIGOUT_NID 0x06 -#define ALC880_DIGIN_NID 0x0a - -static struct hda_input_mux alc880_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x3 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -/* channel source setting (2/6 channel selection for 3-stack) */ -/* 2ch mode */ -static struct hda_verb alc880_threestack_ch2_init[] = { - /* set line-in to input, mute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - /* set mic-in to input vref 80%, mute it */ - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* 6ch mode */ -static struct hda_verb alc880_threestack_ch6_init[] = { - /* set line-in to output, unmute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - /* set mic-in to output, unmute it */ - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { } /* end */ -}; - -static struct alc_channel_mode alc880_threestack_modes[2] = { - { 2, alc880_threestack_ch2_init }, - { 6, alc880_threestack_ch6_init }, -}; - -static snd_kcontrol_new_t alc880_three_stack_mixer[] = { +static snd_kcontrol_new_t alc880_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), + 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), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + 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), @@ -369,7 +360,25 @@ static snd_kcontrol_new_t alc880_three_stack_mixer[] = { 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", @@ -380,14 +389,37 @@ static snd_kcontrol_new_t alc880_three_stack_mixer[] = { { } /* end */ }; -/* capture mixer elements */ -static snd_kcontrol_new_t alc880_capture_mixer[] = { +/* 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), - 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 @@ -396,20 +428,37 @@ static snd_kcontrol_new_t alc880_capture_mixer[] = { */ /* .name = "Capture Source", */ .name = "Input Source", - .count = 3, + .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 */ }; -/* capture mixer elements (in case NID 0x07 not available) */ -static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), +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 @@ -418,7 +467,7 @@ static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { */ /* .name = "Capture Source", */ .name = "Input Source", - .count = 2, + .count = 3, .info = alc_mux_enum_info, .get = alc_mux_enum_get, .put = alc_mux_enum_put, @@ -426,268 +475,7 @@ static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { { } /* end */ }; - - -/* - * ALC880 5-stack model - * - * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd) - * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 - * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 - */ - -/* additional mixers to alc880_three_stack_mixer */ -static snd_kcontrol_new_t alc880_five_stack_mixer[] = { - HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), - { } /* end */ -}; - -/* channel source setting (6/8 channel selection for 5-stack) */ -/* 6ch mode */ -static struct hda_verb alc880_fivestack_ch6_init[] = { - /* set line-in to input, mute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* 8ch mode */ -static struct hda_verb alc880_fivestack_ch8_init[] = { - /* set line-in to output, unmute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { } /* end */ -}; - -static struct alc_channel_mode alc880_fivestack_modes[2] = { - { 6, alc880_fivestack_ch6_init }, - { 8, alc880_fivestack_ch8_init }, -}; - - -/* - * ALC880 6-stack model - * - * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f) - * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, - * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b - */ - -static hda_nid_t alc880_6st_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x03, 0x04, 0x05 -}; - -static struct hda_input_mux alc880_6stack_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -/* fixed 8-channels */ -static struct alc_channel_mode alc880_sixstack_modes[1] = { - { 8, NULL }, -}; - -static snd_kcontrol_new_t alc880_six_stack_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), - 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), - { - .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 */ -}; - - -/* - * ALC880 W810 model - * - * 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 hda_nid_t alc880_w810_dac_nids[3] = { - /* front, rear/surround, clfe */ - 0x02, 0x03, 0x04 -}; - -/* fixed 6 channels */ -static struct alc_channel_mode alc880_w810_modes[1] = { - { 6, NULL } -}; - -/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ -static snd_kcontrol_new_t alc880_w810_base_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - { } /* end */ -}; - - -/* - * Z710V model - * - * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) - * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a - */ - -static hda_nid_t alc880_z71v_dac_nids[1] = { - 0x02 -}; -#define ALC880_Z71V_HP_DAC 0x03 - -/* fixed 2 channels */ -static struct alc_channel_mode alc880_2_jack_modes[1] = { - { 2, NULL } -}; - -static snd_kcontrol_new_t alc880_z71v_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - { } /* end */ -}; - - -/* FIXME! */ -/* - * ALC880 F1734 model - * - * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) - * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 - */ - -static hda_nid_t alc880_f1734_dac_nids[1] = { - 0x03 -}; -#define ALC880_F1734_HP_DAC 0x02 - -static snd_kcontrol_new_t alc880_f1734_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - { } /* end */ -}; - - -/* FIXME! */ -/* - * ALC880 ASUS model - * - * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) - * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, - * Mic = 0x18, Line = 0x1a - */ - -#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ -#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ - -static snd_kcontrol_new_t alc880_asus_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - 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), - { - .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 */ -}; - -/* FIXME! */ -/* - * ALC880 ASUS W1V model - * - * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) - * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, - * Mic = 0x18, Line = 0x1a, Line2 = 0x1b - */ - -/* additional mixers to alc880_asus_mixer */ -static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = { - HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), - { } /* end */ -}; - - /* - * build control elements */ static int alc_build_controls(struct hda_codec *codec) { @@ -714,297 +502,227 @@ static int alc_build_controls(struct hda_codec *codec) return 0; } - /* * initialize the codec volumes, etc */ -/* - * generic initialization of ADC, input mixers and output mixers - */ -static struct hda_verb alc880_volume_init_verbs[] = { - /* - * Unmute ADC0-2 and set the default input to mic-in - */ - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget +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 Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - - /* - * Set up output mixers (0x0c - 0x0f) + /* 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 */ - /* set vol=0 to output mixers */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* set up input amps for analog loopback */ - /* Amp Indices: DAC = 0, mixer = 1 */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + /* 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))}, { } }; -/* - * 3-stack pin configuration: - * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b - */ -static struct hda_verb alc880_pin_3stack_init_verbs[] = { - /* - * preset connection lists of input pins - * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround - */ - {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ - - /* - * Set pin mode and muting - */ - /* set front pin widgets 0x14 for output */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Mic1 (rear panel) pin widget for input and vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mic2 (as headphone out) for HP output */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, +static struct hda_verb alc880_init_verbs_five_stack[] = { /* Line In pin widget for input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line2 (as front mic) pin widget for input and vref at 80% */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {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))}, { } }; -/* - * 5-stack pin configuration: - * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, - * line-in/side = 0x1a, f-mic = 0x1b - */ -static struct hda_verb alc880_pin_5stack_init_verbs[] = { - /* - * preset connection lists of input pins - * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround - */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ +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}, - /* - * Set pin mode and muting - */ - /* set pin widgets 0x14-0x17 for output */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* unmute pins for output (no gain on this amp) */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, - /* Mic1 (rear panel) pin widget for input and vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mic2 (as headphone out) for HP output */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Line In pin widget for input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line2 (as front mic) pin widget for input and vref at 80% */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* 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}, -/* - * W810 pin configuration: - * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b - */ -static struct hda_verb alc880_pin_w810_init_verbs[] = { - /* hphone/speaker input selector: front DAC */ - {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, + /* front out pin: NOT headphone enable, out enable, vref disabled */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* 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}, -/* - * Z71V pin configuration: - * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) - */ -static struct hda_verb alc880_pin_z71v_init_verbs[] = { - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* surround channel selector/amp: output 0: unmuted, max volume */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* 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}, -/* - * 6-stack pin configuration: - * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19, - * line = 0x1a, HP = 0x1b - */ -static struct hda_verb alc880_pin_6stack_init_verbs[] = { - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; -/* FIXME! */ -/* - * F1734 pin configuration: - * HP = 0x14, speaker-out = 0x15, mic = 0x18 - */ -static struct hda_verb alc880_pin_f1734_init_verbs[] = { - {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* 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}, -/* FIXME! */ -/* - * ASUS pin configuration: - * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a - */ -static struct hda_verb alc880_pin_asus_init_verbs[] = { - {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; + /* c/lfe channel selector/amp: output 0: unmuted, max volume */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, -/* Enable GPIO mask and set output */ -static struct hda_verb alc880_gpio1_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, -}; + /* c/lfe out pin: muted, (no volume selection) */ + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, -/* Enable GPIO mask and set output */ -static struct hda_verb alc880_gpio2_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, -}; + /* 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; - unsigned int i; - - for (i = 0; i < spec->num_init_verbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); + snd_hda_sequence_write(codec, spec->init_verbs); return 0; } @@ -1018,8 +736,9 @@ static int alc_resume(struct hda_codec *codec) int i; alc_init(codec); - for (i = 0; i < spec->num_mixers; i++) + 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) @@ -1060,1070 +779,295 @@ static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, } /* - * 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 is set in alc_build_pcms */ - .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 is set in alc_build_pcms */ - .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_PLAYBACK].nid = spec->multiout.dac_nids[0]; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; - - 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) -{ - struct alc_spec *spec = codec->spec; - unsigned int i; - - if (! spec) - return; - - if (spec->kctl_alloc) { - for (i = 0; i < spec->num_kctl_used; i++) - kfree(spec->kctl_alloc[i].name); - kfree(spec->kctl_alloc); - } - kfree(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 -}; - - -/* - * Test configuration for debugging - * - * Almost all inputs/outputs are enabled. I/O pins can be configured via - * enum controls. - */ -#ifdef CONFIG_SND_DEBUG -static hda_nid_t alc880_test_dac_nids[4] = { - 0x02, 0x03, 0x04, 0x05 -}; - -static struct hda_input_mux alc880_test_capture_source = { - .num_items = 5, - .items = { - { "In-1", 0x0 }, - { "In-2", 0x1 }, - { "In-3", 0x2 }, - { "In-4", 0x3 }, - { "CD", 0x4 }, - }, -}; - -static struct alc_channel_mode alc880_test_modes[4] = { - { 2, NULL }, - { 4, NULL }, - { 6, NULL }, - { 8, NULL }, -}; - -static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - static char *texts[] = { - "N/A", "Line Out", "HP Out", - "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item >= 8) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - unsigned int pin_ctl, item = 0; - - pin_ctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (pin_ctl & AC_PINCTL_OUT_EN) { - if (pin_ctl & AC_PINCTL_HP_EN) - item = 2; - else - item = 1; - } else if (pin_ctl & AC_PINCTL_IN_EN) { - switch (pin_ctl & AC_PINCTL_VREFEN) { - case AC_PINCTL_VREF_HIZ: item = 3; break; - case AC_PINCTL_VREF_50: item = 4; break; - case AC_PINCTL_VREF_GRD: item = 5; break; - case AC_PINCTL_VREF_80: item = 6; break; - case AC_PINCTL_VREF_100: item = 7; break; - } - } - ucontrol->value.enumerated.item[0] = item; - return 0; -} - -static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - static unsigned int ctls[] = { - 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, - }; - unsigned int old_ctl, new_ctl; - - old_ctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - new_ctl = ctls[ucontrol->value.enumerated.item[0]]; - if (old_ctl != new_ctl) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); - return 1; - } - return 0; -} - -static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - static char *texts[] = { - "Front", "Surround", "CLFE", "Side" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= 4) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - unsigned int sel; - - sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); - ucontrol->value.enumerated.item[0] = sel & 3; - return 0; -} - -static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - unsigned int sel; - - sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; - if (ucontrol->value.enumerated.item[0] != sel) { - sel = ucontrol->value.enumerated.item[0] & 3; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); - return 1; - } - return 0; -} - -#define PIN_CTL_TEST(xname,nid) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = alc_test_pin_ctl_info, \ - .get = alc_test_pin_ctl_get, \ - .put = alc_test_pin_ctl_put, \ - .private_value = nid \ - } - -#define PIN_SRC_TEST(xname,nid) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = alc_test_pin_src_info, \ - .get = alc_test_pin_src_get, \ - .put = alc_test_pin_src_put, \ - .private_value = nid \ - } - -static snd_kcontrol_new_t alc880_test_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT), - ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT), - PIN_CTL_TEST("Front Pin Mode", 0x14), - PIN_CTL_TEST("Surround Pin Mode", 0x15), - PIN_CTL_TEST("CLFE Pin Mode", 0x16), - PIN_CTL_TEST("Side Pin Mode", 0x17), - PIN_CTL_TEST("In-1 Pin Mode", 0x18), - PIN_CTL_TEST("In-2 Pin Mode", 0x19), - PIN_CTL_TEST("In-3 Pin Mode", 0x1a), - PIN_CTL_TEST("In-4 Pin Mode", 0x1b), - PIN_SRC_TEST("In-1 Pin Source", 0x18), - PIN_SRC_TEST("In-2 Pin Source", 0x19), - PIN_SRC_TEST("In-3 Pin Source", 0x1a), - PIN_SRC_TEST("In-4 Pin Source", 0x1b), - HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "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 struct hda_verb alc880_test_init_verbs[] = { - /* Unmute inputs of 0x0c - 0x0f */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Vol output for 0x0c-0x0f */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Set output pins 0x14-0x17 */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Unmute output pins 0x14-0x17 */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Set input pins 0x18-0x1c */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Mute input pins 0x18-0x1b */ - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* ADC set up */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Analog input/passthru */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - { } -}; -#endif - -/* - */ - -static struct hda_board_config alc880_cfg_tbl[] = { - /* Back 3 jack, front 2 jack */ - { .modelname = "3stack", .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, - - /* Back 3 jack, front 2 jack (Internal add Aux-In) */ - { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST }, - { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, - - /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ - { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, - - /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG }, - { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG }, - - /* Back 5 jack, front 2 jack */ - { .modelname = "5stack", .config = ALC880_5ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST }, - { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST }, - - /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ - { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, - { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, - - { .modelname = "w810", .config = ALC880_W810 }, - { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, - - { .modelname = "z71v", .config = ALC880_Z71V }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, - - { .modelname = "6statack-digout", .config = ALC880_6ST_DIG }, - { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, - { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, - { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG }, - - { .modelname = "asus", .config = ALC880_ASUS }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, - - { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, - { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG }, - - { .modelname = "F1734", .config = ALC880_F1734 }, - { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, - -#ifdef CONFIG_SND_DEBUG - { .modelname = "test", .config = ALC880_TEST }, -#endif - - {} -}; - -/* - * configuration template - to be copied to the spec instance - */ -struct alc_config_preset { - snd_kcontrol_new_t *mixers[4]; - const struct hda_verb *init_verbs[4]; - unsigned int num_dacs; - hda_nid_t *dac_nids; - hda_nid_t dig_out_nid; /* optional */ - hda_nid_t hp_nid; /* optional */ - unsigned int num_adc_nids; - hda_nid_t *adc_nids; - unsigned int num_channel_mode; - const struct alc_channel_mode *channel_mode; - const struct hda_input_mux *input_mux; -}; - -static struct alc_config_preset alc880_presets[] = { - [ALC880_3ST] = { - .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_3ST_DIG] = { - .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_5ST] = { - .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), - .channel_mode = alc880_fivestack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_5ST_DIG] = { - .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), - .channel_mode = alc880_fivestack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_6ST_DIG] = { - .mixers = { alc880_six_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), - .dac_nids = alc880_6st_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), - .channel_mode = alc880_sixstack_modes, - .input_mux = &alc880_6stack_capture_source, - }, - [ALC880_W810] = { - .mixers = { alc880_w810_base_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), - .dac_nids = alc880_w810_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), - .channel_mode = alc880_w810_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_Z71V] = { - .mixers = { alc880_z71v_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs, - alc880_gpio2_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), - .dac_nids = alc880_z71v_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .hp_nid = 0x03, - .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), - .channel_mode = alc880_2_jack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_F1734] = { - .mixers = { alc880_f1734_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), - .dac_nids = alc880_f1734_dac_nids, - .hp_nid = 0x02, - .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), - .channel_mode = alc880_2_jack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_ASUS] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_ASUS_DIG] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_ASUS_W1V] = { - .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_UNIWILL_DIG] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .input_mux = &alc880_capture_source, - }, -#ifdef CONFIG_SND_DEBUG - [ALC880_TEST] = { - .mixers = { alc880_test_mixer }, - .init_verbs = { alc880_test_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), - .dac_nids = alc880_test_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_test_modes), - .channel_mode = alc880_test_modes, - .input_mux = &alc880_test_capture_source, - }, -#endif -}; - -/* - * Automatic parse of I/O pins from the BIOS configuration - */ - -#define NUM_CONTROL_ALLOC 32 -#define NUM_VERB_ALLOC 32 - -enum { - ALC_CTL_WIDGET_VOL, - ALC_CTL_WIDGET_MUTE, - ALC_CTL_BIND_MUTE, -}; -static snd_kcontrol_new_t alc880_control_templates[] = { - HDA_CODEC_VOLUME(NULL, 0, 0, 0), - HDA_CODEC_MUTE(NULL, 0, 0, 0), - ALC_BIND_MUTE(NULL, 0, 0, 0), -}; - -/* add dynamic controls */ -static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val) -{ - snd_kcontrol_new_t *knew; - - if (spec->num_kctl_used >= spec->num_kctl_alloc) { - int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; - - knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ - if (! knew) - return -ENOMEM; - if (spec->kctl_alloc) { - memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); - kfree(spec->kctl_alloc); - } - spec->kctl_alloc = knew; - spec->num_kctl_alloc = num; - } - - knew = &spec->kctl_alloc[spec->num_kctl_used]; - *knew = alc880_control_templates[type]; - knew->name = snd_kmalloc_strdup(name, GFP_KERNEL); - if (! knew->name) - return -ENOMEM; - knew->private_value = val; - spec->num_kctl_used++; - return 0; -} - -#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) -#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) -#define alc880_is_multi_pin(nid) ((nid) >= 0x18) -#define alc880_multi_pin_idx(nid) ((nid) - 0x18) -#define alc880_is_input_pin(nid) ((nid) >= 0x18) -#define alc880_input_pin_idx(nid) ((nid) - 0x18) -#define alc880_idx_to_dac(nid) ((nid) + 0x02) -#define alc880_dac_to_idx(nid) ((nid) - 0x02) -#define alc880_idx_to_mixer(nid) ((nid) + 0x0c) -#define alc880_idx_to_selector(nid) ((nid) + 0x10) -#define ALC880_PIN_CD_NID 0x1c - -/* fill in the dac_nids table from the parsed pin configuration */ -static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) -{ - hda_nid_t nid; - int assigned[4]; - int i, j; - - memset(assigned, 0, sizeof(assigned)); - - /* check the pins hardwired to audio widget */ - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - if (alc880_is_fixed_pin(nid)) { - int idx = alc880_fixed_pin_idx(nid); - spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx); - assigned[idx] = 1; - } - } - /* left pins can be connect to any audio widget */ - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - if (alc880_is_fixed_pin(nid)) - continue; - /* search for an empty channel */ - for (j = 0; j < cfg->line_outs; j++) { - if (! assigned[j]) { - spec->multiout.dac_nids[i] = alc880_idx_to_dac(j); - assigned[j] = 1; - break; - } - } - } - spec->multiout.num_dacs = cfg->line_outs; - return 0; -} - -/* add playback controls from the parsed DAC table */ -static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) -{ - char name[32]; - static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; - hda_nid_t nid; - int i, err; - - for (i = 0; i < cfg->line_outs; i++) { - if (! spec->multiout.dac_nids[i]) - continue; - nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); - if (i == 2) { - /* Center/LFE */ - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) - return err; - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) - return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0) - return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0) - return err; - } else { - sprintf(name, "%s Playback Volume", chname[i]); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) - return err; - sprintf(name, "%s Playback Switch", chname[i]); - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) - return err; - } - } - - return 0; -} - -/* add playback controls for HP output */ -static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) -{ - hda_nid_t nid; - int err; - - if (! pin) - return 0; - - if (alc880_is_fixed_pin(pin)) { - nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); - if (! spec->multiout.dac_nids[0]) { - /* use this as the primary output */ - spec->multiout.dac_nids[0] = nid; - if (! spec->multiout.num_dacs) - spec->multiout.num_dacs = 1; - } else - /* specify the DAC as the extra HP output */ - spec->multiout.hp_nid = nid; - /* control HP volume/switch on the output mixer amp */ - nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) - return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) - return err; - } else if (alc880_is_multi_pin(pin)) { - /* set manual connection */ - if (! spec->multiout.dac_nids[0]) { - /* use this as the primary output */ - spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); - if (! spec->multiout.num_dacs) - spec->multiout.num_dacs = 1; - } - /* we have only a switch on HP-out PIN */ - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0) - return err; - } - return 0; -} - -/* create input playback/capture controls for the given pin */ -static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname) -{ - char name[32]; - int err, idx; - - sprintf(name, "%s Playback Volume", ctlname); - idx = alc880_input_pin_idx(pin); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) - return err; - sprintf(name, "%s Playback Switch", ctlname); - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) - return err; - return 0; -} - -/* create playback/capture controls for input pins */ -static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) + * Digital out + */ +static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) { - static char *labels[AUTO_PIN_LAST] = { - "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" - }; - struct hda_input_mux *imux = &spec->private_imux; - int i, err; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (alc880_is_input_pin(cfg->input_pins[i])) { - err = new_analog_input(spec, cfg->input_pins[i], labels[i]); - if (err < 0) - return err; - imux->items[imux->num_items].label = labels[i]; - imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]); - imux->num_items++; - } - } - return 0; + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); } -static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, - int dac_idx) +static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + snd_pcm_substream_t *substream) { - /* set as output */ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - /* need the manual connection? */ - if (alc880_is_multi_pin(nid)) { - struct alc_spec *spec = codec->spec; - int idx = alc880_multi_pin_idx(nid); - snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, - AC_VERB_SET_CONNECT_SEL, - alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); - } + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); } -static void alc880_auto_init_multi_out(struct hda_codec *codec) +/* + * 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; - int i; - for (i = 0; i < spec->autocfg.line_outs; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; - alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); - } + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], + stream_tag, 0, format); + return 0; } -static void alc880_auto_init_hp_out(struct hda_codec *codec) +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; - hda_nid_t pin; - pin = spec->autocfg.hp_pin; - if (pin) /* connect to front */ - alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); + return 0; } -static void alc880_auto_init_analog_input(struct hda_codec *codec) + +/* + */ +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; - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (alc880_is_input_pin(nid)) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); - if (nid != ALC880_PIN_CD_NID) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); + 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; } -/* parse the BIOS configuration and set up the alc_spec */ -/* return 1 if successful, 0 if the proper config is not found, or a negative error code */ -static int alc880_parse_auto_config(struct hda_codec *codec) +static void alc_free(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; - int err; + 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 +}; - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) - return err; - if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0) - return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) - return 0; /* can't find valid BIOS pin config */ - if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || - (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) - return err; +/* + */ - spec->multiout.max_channels = spec->multiout.num_dacs * 2; +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 }, - if (spec->autocfg.dig_out_pin) - spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; - if (spec->autocfg.dig_in_pin) - spec->dig_in_nid = ALC880_DIGIN_NID; + /* Back 3 jack, front 2 jack (Internal add Aux-In) */ + { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST }, - if (spec->kctl_alloc) - spec->mixers[spec->num_mixers++] = spec->kctl_alloc; + /* 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 }, - spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; + /* 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 }, - spec->input_mux = &spec->private_imux; + /* 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 }, - return 1; -} + /* 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 }, -/* init callback for auto-configuration model -- overriding the default init */ -static int alc880_auto_init(struct hda_codec *codec) -{ - alc_init(codec); - alc880_auto_init_multi_out(codec); - alc880_auto_init_hp_out(codec); - alc880_auto_init_analog_input(codec); - return 0; -} + { .modelname = "w810", .config = ALC880_W810 }, + { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 }, -/* - * OK, here we have finally the patch for ALC880 - */ + {} +}; static int patch_alc880(struct hda_codec *codec) { struct alc_spec *spec; int board_config; - int i, err; spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->bind_mutex); codec->spec = spec; board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); - if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { - printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n"); - board_config = ALC880_AUTO; + if (board_config < 0) { + snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n"); + board_config = ALC880_MINIMAL; } - if (board_config == ALC880_AUTO) { - /* automatic parse from the BIOS config */ - err = alc880_parse_auto_config(codec); - if (err < 0) { - alc_free(codec); - return err; - } else if (! err) { - printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n"); - board_config = ALC880_3ST; - } + 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; } - if (board_config != ALC880_AUTO) { - /* set up from the preset table */ - const struct alc_config_preset *preset; - - preset = &alc880_presets[board_config]; - - for (i = 0; preset->mixers[i]; i++) { - snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break); - spec->mixers[spec->num_mixers++] = preset->mixers[i]; - } - for (i = 0; preset->init_verbs[i]; i++) { - snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break); - spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i]; - } - - spec->channel_mode = preset->channel_mode; - spec->num_channel_mode = preset->num_channel_mode; - - spec->multiout.max_channels = spec->channel_mode[0].channels; - - spec->multiout.num_dacs = preset->num_dacs; - spec->multiout.dac_nids = preset->dac_nids; - spec->multiout.dig_out_nid = preset->dig_out_nid; - spec->multiout.hp_nid = preset->hp_nid; + 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; + } - spec->input_mux = preset->input_mux; + 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; + } - spec->num_adc_nids = preset->num_adc_nids; - spec->adc_nids = preset->adc_nids; + 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"; @@ -2134,64 +1078,34 @@ static int patch_alc880(struct hda_codec *codec) spec->stream_digital_playback = &alc880_pcm_digital_playback; spec->stream_digital_capture = &alc880_pcm_digital_capture; - if (! spec->adc_nids && spec->input_mux) { - /* check whether NID 0x07 is valid */ - unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0], - AC_PAR_AUDIO_WIDGET_CAP); - wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ - if (wcap != AC_WID_AUD_IN) { - spec->adc_nids = alc880_adc_nids_alt; - spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); - spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer; - spec->num_mixers++; - } else { - spec->adc_nids = alc880_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); - spec->mixers[spec->num_mixers] = alc880_capture_mixer; - spec->num_mixers++; - } + 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; - if (board_config == ALC880_AUTO) - codec->patch_ops.init = alc880_auto_init; return 0; } - /* * ALC260 support */ -static hda_nid_t alc260_dac_nids[1] = { - /* front */ - 0x02, -}; - -static hda_nid_t alc260_adc_nids[1] = { - /* ADC0 */ - 0x04, -}; - -static hda_nid_t alc260_hp_adc_nids[1] = { - /* ADC1 */ - 0x05, -}; - -#define ALC260_DIGOUT_NID 0x03 -#define ALC260_DIGIN_NID 0x06 - -static struct hda_input_mux alc260_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - /* * 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 @@ -2202,9 +1116,11 @@ static struct alc_channel_mode alc260_modes[1] = { { 2, NULL }, }; -static snd_kcontrol_new_t alc260_base_mixer[] = { +snd_kcontrol_new_t alc260_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), + /* use LINE2 for the output */ + /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */ + HDA_CODEC_MUTE("Front Playback Switch", 0x15, 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), @@ -2216,9 +1132,9 @@ static snd_kcontrol_new_t alc260_base_mixer[] = { 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), - ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), { @@ -2231,91 +1147,60 @@ static snd_kcontrol_new_t alc260_base_mixer[] = { { } /* end */ }; -static snd_kcontrol_new_t alc260_hp_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), - 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("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x05, 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, PIN_IN}, + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, /* CD pin widget for input */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {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, PIN_VREF80}, + {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, PIN_VREF80}, + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, /* LINE-2 is used for line-out in rear */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, /* select line-out */ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* LINE-OUT pin */ - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, /* enable HP */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, /* enable Mono */ - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* mute capture amp left and right */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + /* 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}, - /* mute capture amp left and right */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* set connection select to line in (default select for this ADC) */ - {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* set vol=0 Line-Out mixer amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* unmute pin widget amp left and right (no gain on this amp) */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* set vol=0 HP mixer amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* unmute pin widget amp left and right (no gain on this amp) */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* set vol=0 Mono mixer amp left and right */ - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* unmute pin widget amp left and right (no gain on this amp) */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* unmute LINE-2 out pin */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* 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, 0xb000}, + /* 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, 0xb080}, + /* unmute Mono mixer amp left and right (volume = 0) */ + {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* mute pin widget amp left and right (no gain on this amp) */ + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + /* mute LINE-2 out */ + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ - /* mute CD */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - /* mute Line In */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - /* mute Mic */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + /* 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 */ - /* mute Front out path */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* mute Headphone out path */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* mute Mono out path */ - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + /* 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))}, + /* Unmute Mono out path */ + {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, { } }; @@ -2323,52 +1208,30 @@ 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, -}; - -static struct hda_board_config alc260_cfg_tbl[] = { - { .modelname = "hp", .config = ALC260_HP }, - { .pci_subvendor = 0x103c, .config = ALC260_HP }, - {} + .nid = 0x4, }; static int patch_alc260(struct hda_codec *codec) { struct alc_spec *spec; - int board_config; spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->bind_mutex); codec->spec = spec; - board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); - if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { - snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); - board_config = ALC260_BASIC; - } - - switch (board_config) { - case ALC260_HP: - spec->mixers[spec->num_mixers] = alc260_hp_mixer; - spec->num_mixers++; - break; - default: - spec->mixers[spec->num_mixers] = alc260_base_mixer; - spec->num_mixers++; - break; - } - - spec->init_verbs[0] = alc260_init_verbs; - spec->num_init_verbs = 1; + 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); @@ -2381,23 +1244,14 @@ static int patch_alc260(struct hda_codec *codec) spec->multiout.dac_nids = alc260_dac_nids; spec->input_mux = &alc260_capture_source; - switch (board_config) { - case ALC260_HP: - spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids); - spec->adc_nids = alc260_hp_adc_nids; - break; - default: - spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); - spec->adc_nids = alc260_adc_nids; - break; - } + 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 * @@ -2470,15 +1324,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u */ static snd_kcontrol_new_t alc882_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + 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), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, 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), - ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), + 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), @@ -2510,80 +1364,89 @@ static snd_kcontrol_new_t alc882_base_mixer[] = { 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, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {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, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {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, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {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, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - - /* Front Pin: output 0 (0x0c) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {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: output 1 (0x0d) */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* 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: output 2 (0x0e) */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* 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: output 3 (0x0f) */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* 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}, - /* Mic (rear) pin: input vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line In pin: input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line-2 In: Headphone output (output 0 - 0x0c) */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* 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, PIN_IN}, + {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, AMP_IN_UNMUTE(0)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + {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, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + {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, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* ADC1: mute amp left and right */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC2: mute amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC3: mute amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, + {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))}, { } }; @@ -2596,7 +1459,6 @@ static int patch_alc882(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->bind_mutex); codec->spec = spec; spec->mixers[spec->num_mixers] = alc882_base_mixer; @@ -2604,9 +1466,8 @@ static int patch_alc882(struct hda_codec *codec) spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; spec->dig_in_nid = ALC880_DIGIN_NID; - spec->init_verbs[0] = alc882_init_verbs; - spec->num_init_verbs = 1; - + 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); diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c deleted file mode 100644 index 013be2ea513a..000000000000 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * HD audio interface patch for SigmaTel STAC92xx - * - * Copyright (c) 2005 Embedded Alley Solutions, Inc. - * - * - * Based on patch_cmedia.c and patch_realtek.c - * 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" - -#undef STAC_TEST - -struct sigmatel_spec { - /* playback */ - struct hda_multi_out multiout; - hda_nid_t playback_nid; - - /* capture */ - hda_nid_t *adc_nids; - unsigned int num_adcs; - hda_nid_t *mux_nids; - unsigned int num_muxes; - hda_nid_t capture_nid; - hda_nid_t dig_in_nid; - - /* power management*/ - hda_nid_t *pstate_nids; - unsigned int num_pstates; - - /* pin widgets */ - hda_nid_t *pin_nids; - unsigned int num_pins; -#ifdef STAC_TEST - unsigned int *pin_configs; -#endif - - /* codec specific stuff */ - struct hda_verb *init; - snd_kcontrol_new_t *mixer; - - /* capture source */ - struct hda_input_mux input_mux; - char input_labels[HDA_MAX_NUM_INPUTS][16]; - unsigned int cur_mux[2]; - - /* channel mode */ - unsigned int num_ch_modes; - unsigned int cur_ch_mode; - const struct sigmatel_channel_mode *channel_modes; - - struct hda_pcm pcm_rec[1]; /* PCM information */ -}; - -static hda_nid_t stac9200_adc_nids[1] = { - 0x03, -}; - -static hda_nid_t stac9200_mux_nids[1] = { - 0x0c, -}; - -static hda_nid_t stac9200_dac_nids[1] = { - 0x02, -}; - -static hda_nid_t stac9200_pstate_nids[3] = { - 0x01, 0x02, 0x03, -}; - -static hda_nid_t stac9200_pin_nids[8] = { - 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, -}; - -static hda_nid_t stac922x_adc_nids[2] = { - 0x06, 0x07, -}; - -static hda_nid_t stac922x_mux_nids[2] = { - 0x12, 0x13, -}; - -static hda_nid_t stac922x_dac_nids[4] = { - 0x02, 0x03, 0x04, 0x05, -}; - -static hda_nid_t stac922x_pstate_nids[8] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11, -}; - -static hda_nid_t stac922x_pin_nids[10] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x15, 0x1b, -}; - -static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - return snd_hda_input_mux_info(&spec->input_mux, uinfo); -} - -static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_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 stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_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->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); -} - -static struct hda_verb stac9200_ch2_init[] = { - /* set dac0mux for dac converter */ - { 0x07, 0x701, 0x00}, - {} -}; - -static struct hda_verb stac922x_ch2_init[] = { - /* set master volume and direct control */ - { 0x16, 0x70f, 0xff}, - {} -}; - -struct sigmatel_channel_mode { - unsigned int channels; - const struct hda_verb *sequence; -}; - -static snd_kcontrol_new_t stac9200_mixer[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT), - { } /* end */ -}; - -static snd_kcontrol_new_t stac922x_mixer[] = { - HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static int stac92xx_build_controls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int err; - - err = snd_hda_add_new_ctls(codec, spec->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; -} - -#ifdef STAC_TEST -static unsigned int stac9200_pin_configs[8] = { - 0x01c47010, 0x01447010, 0x0221401f, 0x01114010, - 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, -}; - -static unsigned int stac922x_pin_configs[14] = { - 0x40000100, 0x40000100, 0x40000100, 0x01114010, - 0x01813122, 0x40000100, 0x01447010, 0x01c47010, - 0x40000100, 0x40000100, -}; - -static void stac92xx_set_config_regs(struct hda_codec *codec) -{ - int i; - struct sigmatel_spec *spec = codec->spec; - unsigned int pin_cfg; - - for (i=0; i < spec->num_pins; i++) { - snd_hda_codec_write(codec, spec->pin_nids[i], 0, - AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, - spec->pin_configs[i] & 0x000000ff); - snd_hda_codec_write(codec, spec->pin_nids[i], 0, - AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, - (spec->pin_configs[i] & 0x0000ff00) >> 8); - snd_hda_codec_write(codec, spec->pin_nids[i], 0, - AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, - (spec->pin_configs[i] & 0x00ff0000) >> 16); - snd_hda_codec_write(codec, spec->pin_nids[i], 0, - AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, - spec->pin_configs[i] >> 24); - pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, - AC_VERB_GET_CONFIG_DEFAULT, - 0x00); - printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg); - } -} -#endif - -static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value) -{ - unsigned int pin_ctl; - - pin_ctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0x00); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_ctl | value); - - return 0; -} - -static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT; - unsigned int vref_ctl = AC_PINCTL_VREF_HIZ; - - if (vref_caps & AC_PINCAP_VREF_100) - vref_ctl = AC_PINCTL_VREF_100; - else if (vref_caps & AC_PINCAP_VREF_80) - vref_ctl = AC_PINCTL_VREF_80; - else if (vref_caps & AC_PINCAP_VREF_50) - vref_ctl = AC_PINCTL_VREF_50; - else if (vref_caps & AC_PINCAP_VREF_GRD) - vref_ctl = AC_PINCTL_VREF_GRD; - - stac92xx_set_pinctl(codec, nid, vref_ctl); - - return 0; -} - -/* - * retrieve the default device type from the default config value - */ -#define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) -#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) - -static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg) -{ - struct sigmatel_spec *spec = codec->spec; - u32 location = get_defcfg_location(pin_cfg); - char *label; - const char *type = NULL; - int ainput = 0; - - switch(get_defcfg_type(pin_cfg)) { - case AC_JACK_HP_OUT: - /* Enable HP amp */ - stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN); - /* Fall through */ - case AC_JACK_SPDIF_OUT: - case AC_JACK_LINE_OUT: - case AC_JACK_SPEAKER: - /* Enable output */ - stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); - break; - case AC_JACK_SPDIF_IN: - stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); - break; - case AC_JACK_MIC_IN: - if ((location & 0x0f) == AC_JACK_LOC_FRONT) - type = "Front Mic"; - else - type = "Mic"; - ainput = 1; - /* Set vref */ - stac92xx_set_vref(codec, nid); - stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); - break; - case AC_JACK_CD: - type = "CD"; - ainput = 1; - stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); - break; - case AC_JACK_LINE_IN: - if ((location & 0x0f) == AC_JACK_LOC_FRONT) - type = "Front Line"; - else - type = "Line"; - ainput = 1; - stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); - break; - case AC_JACK_AUX: - if ((location & 0x0f) == AC_JACK_LOC_FRONT) - type = "Front Aux"; - else - type = "Aux"; - ainput = 1; - stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); - break; - } - - if (ainput) { - hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; - int i, j, num_cons, index = -1; - if (!type) - type = "Input"; - label = spec->input_labels[spec->input_mux.num_items]; - strcpy(label, type); - spec->input_mux.items[spec->input_mux.num_items].label = label; - for (i=0; inum_muxes; i++) { - num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS); - for (j=0; j= 0) - break; - } - spec->input_mux.items[spec->input_mux.num_items].index = index; - spec->input_mux.num_items++; - } - - return 0; -} - -static int stac92xx_config_pins(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int i; - unsigned int pin_cfg; - - for (i=0; i < spec->num_pins; i++) { - /* Default to disabled */ - snd_hda_codec_write(codec, spec->pin_nids[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - 0x00); - - pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, - AC_VERB_GET_CONFIG_DEFAULT, - 0x00); - if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE) - continue; /* Move on */ - - stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg); - } - - return 0; -} - -static int stac92xx_init(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int i; - - for (i=0; i < spec->num_pstates; i++) - snd_hda_codec_write(codec, spec->pstate_nids[i], 0, - AC_VERB_SET_POWER_STATE, 0x00); - - mdelay(100); - - snd_hda_sequence_write(codec, spec->init); - -#ifdef STAC_TEST - stac92xx_set_config_regs(codec); -#endif - - stac92xx_config_pins(codec); - - return 0; -} - -/* - * Analog playback callbacks - */ -static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); -} - -static int stac92xx_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 sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital playback callbacks - */ -static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - - -/* - * Analog capture callbacks - */ -static int stac92xx_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 sigmatel_spec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - stream_tag, 0, format); - return 0; -} - -static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - snd_pcm_substream_t *substream) -{ - struct sigmatel_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 stac92xx_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in stac92xx_build_pcms */ - .ops = { - .open = stac92xx_dig_playback_pcm_open, - .close = stac92xx_dig_playback_pcm_close - }, -}; - -static struct hda_pcm_stream stac92xx_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in stac92xx_build_pcms */ -}; - -static struct hda_pcm_stream stac92xx_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0x02, /* NID to query formats and rates */ - .ops = { - .open = stac92xx_playback_pcm_open, - .prepare = stac92xx_playback_pcm_prepare, - .cleanup = stac92xx_playback_pcm_cleanup - }, -}; - -static struct hda_pcm_stream stac92xx_pcm_analog_capture = { - .substreams = 2, - .channels_min = 2, - .channels_max = 2, - .nid = 0x06, /* NID to query formats and rates */ - .ops = { - .prepare = stac92xx_capture_pcm_prepare, - .cleanup = stac92xx_capture_pcm_cleanup - }, -}; - -static int stac92xx_build_pcms(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "STAC92xx"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid; - - if (spec->multiout.dig_out_nid || spec->dig_in_nid) { - codec->num_pcms++; - info++; - info->name = "STAC92xx Digital"; - if (spec->multiout.dig_out_nid) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_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] = stac92xx_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; - } - } - - return 0; -} - -static void stac92xx_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} - -static struct hda_codec_ops stac92xx_patch_ops = { - .build_controls = stac92xx_build_controls, - .build_pcms = stac92xx_build_pcms, - .init = stac92xx_init, - .free = stac92xx_free, -}; - -static int patch_stac9200(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = stac9200_dac_nids; - spec->multiout.dig_out_nid = 0x05; - spec->dig_in_nid = 0x04; - spec->adc_nids = stac9200_adc_nids; - spec->mux_nids = stac9200_mux_nids; - spec->num_muxes = 1; - spec->input_mux.num_items = 0; - spec->pstate_nids = stac9200_pstate_nids; - spec->num_pstates = 3; - spec->pin_nids = stac9200_pin_nids; -#ifdef STAC_TEST - spec->pin_configs = stac9200_pin_configs; -#endif - spec->num_pins = 8; - spec->init = stac9200_ch2_init; - spec->mixer = stac9200_mixer; - spec->playback_nid = 0x02; - spec->capture_nid = 0x03; - - codec->patch_ops = stac92xx_patch_ops; - - return 0; -} - -static int patch_stac922x(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 4; - spec->multiout.dac_nids = stac922x_dac_nids; - spec->multiout.dig_out_nid = 0x08; - spec->dig_in_nid = 0x09; - spec->adc_nids = stac922x_adc_nids; - spec->mux_nids = stac922x_mux_nids; - spec->num_muxes = 2; - spec->input_mux.num_items = 0; - spec->pstate_nids = stac922x_pstate_nids; - spec->num_pstates = 8; - spec->pin_nids = stac922x_pin_nids; -#ifdef STAC_TEST - spec->pin_configs = stac922x_pin_configs; -#endif - spec->num_pins = 10; - spec->init = stac922x_ch2_init; - spec->mixer = stac922x_mixer; - spec->playback_nid = 0x02; - spec->capture_nid = 0x06; - - codec->patch_ops = stac92xx_patch_ops; - - return 0; -} - -/* - * patch entries - */ -struct hda_codec_preset snd_hda_preset_sigmatel[] = { - { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, - { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, - { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, - { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, - { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, - { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, - { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, - {} /* terminator */ -}; diff --git a/trunk/sound/pci/ice1712/amp.c b/trunk/sound/pci/ice1712/amp.c index 289b0b5711e4..779951725e1e 100644 --- a/trunk/sound/pci/ice1712/amp.c +++ b/trunk/sound/pci/ice1712/amp.c @@ -30,39 +30,16 @@ #include #include "ice1712.h" -#include "envy24ht.h" #include "amp.h" -static void wm_put(ice1712_t *ice, int reg, unsigned short val) -{ - unsigned short cval; - cval = (reg << 9) | val; - snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff); -} static int __devinit snd_vt1724_amp_init(ice1712_t *ice) { - static unsigned short wm_inits[] = { - WM_ATTEN_L, 0x0000, /* 0 db */ - WM_ATTEN_R, 0x0000, /* 0 db */ - WM_DAC_CTRL, 0x0008, /* 24bit I2S */ - WM_INT_CTRL, 0x0001, /* 24bit I2S */ - }; - - unsigned int i; - /* only use basic functionality for now */ ice->num_total_dacs = 2; /* only PSDOUT0 is connected */ ice->num_total_adcs = 2; - /* Chaintech AV-710 has another codecs, which need initialization */ - /* initialize WM8728 codec */ - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) { - for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) - wm_put(ice, wm_inits[i], wm_inits[i+1]); - } - return 0; } @@ -76,13 +53,6 @@ static int __devinit snd_vt1724_amp_add_controls(ice1712_t *ice) /* entry point */ struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_AV710, - .name = "Chaintech AV-710", - .model = "av710", - .chip_init = snd_vt1724_amp_init, - .build_controls = snd_vt1724_amp_add_controls, - }, { .subvendor = VT1724_SUBDEVICE_AUDIO2000, .name = "AMP Ltd AUDIO2000", diff --git a/trunk/sound/pci/ice1712/amp.h b/trunk/sound/pci/ice1712/amp.h index a0fc89b48122..d58d43383e83 100644 --- a/trunk/sound/pci/ice1712/amp.h +++ b/trunk/sound/pci/ice1712/amp.h @@ -24,23 +24,9 @@ * */ -#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"\ - "{Chaintech,AV-710}," +#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000}," -#if 0 #define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */ -#else -#define VT1724_SUBDEVICE_AUDIO2000 0x00030003 /* a dummy ID for AMP Audio2000 */ -#endif -#define VT1724_SUBDEVICE_AV710 0x12142417 /* AV710 - the same ID with Audio2000! */ - -/* WM8728 on I2C for AV710 */ -#define WM_DEV 0x36 - -#define WM_ATTEN_L 0x00 -#define WM_ATTEN_R 0x01 -#define WM_DAC_CTRL 0x02 -#define WM_INT_CTRL 0x03 extern struct snd_ice1712_card_info snd_vt1724_amp_cards[]; diff --git a/trunk/sound/pci/ice1712/ice1712.c b/trunk/sound/pci/ice1712/ice1712.c index a2545a5b26c4..79fba6be3503 100644 --- a/trunk/sound/pci/ice1712/ice1712.c +++ b/trunk/sound/pci/ice1712/ice1712.c @@ -2748,7 +2748,7 @@ static struct pci_driver driver = { static int __init alsa_card_ice1712_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_ice1712_exit(void) diff --git a/trunk/sound/pci/ice1712/ice1712.h b/trunk/sound/pci/ice1712/ice1712.h index 5ad4728daa7b..8bb1c58c26a0 100644 --- a/trunk/sound/pci/ice1712/ice1712.h +++ b/trunk/sound/pci/ice1712/ice1712.h @@ -373,11 +373,6 @@ struct _snd_ice1712 { unsigned short master[2]; unsigned short vol[8]; } aureon; - /* AC97 register cache for Phase28 */ - struct phase28_spec { - unsigned short master[2]; - unsigned short vol[8]; - } phase28; /* Hoontech-specific setting */ struct hoontech_spec { unsigned char boxbits[4]; diff --git a/trunk/sound/pci/ice1712/ice1724.c b/trunk/sound/pci/ice1712/ice1724.c index 79b5f12e06fc..95500f06f0c6 100644 --- a/trunk/sound/pci/ice1712/ice1724.c +++ b/trunk/sound/pci/ice1712/ice1724.c @@ -2328,7 +2328,7 @@ static struct pci_driver driver = { static int __init alsa_card_ice1724_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_ice1724_exit(void) diff --git a/trunk/sound/pci/ice1712/phase.c b/trunk/sound/pci/ice1712/phase.c index 5bf734b04fa0..d1f90832443c 100644 --- a/trunk/sound/pci/ice1712/phase.c +++ b/trunk/sound/pci/ice1712/phase.c @@ -45,47 +45,6 @@ #include "envy24ht.h" #include "phase.h" -/* WM8770 registers */ -#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ -#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ -#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */ -#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */ -#define WM_PHASE_SWAP 0x12 /* DAC phase */ -#define WM_DAC_CTRL1 0x13 /* DAC control bits */ -#define WM_MUTE 0x14 /* mute controls */ -#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */ -#define WM_INT_CTRL 0x16 /* interface control */ -#define WM_MASTER 0x17 /* master clock and mode */ -#define WM_POWERDOWN 0x18 /* power-down controls */ -#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */ -#define WM_ADC_MUX 0x1b /* input MUX */ -#define WM_OUT_MUX1 0x1c /* output MUX */ -#define WM_OUT_MUX2 0x1e /* output MUX */ -#define WM_RESET 0x1f /* software reset */ - - -/* - * Logarithmic volume values for WM8770 - * Computed as 20 * Log10(255 / x) - */ -static unsigned char wm_vol[256] = { - 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, - 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, - 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 -}; - -#define WM_VOL_MAX (sizeof(wm_vol) - 1) -#define WM_VOL_MUTE 0x8000 - static akm4xxx_t akm_phase22 __devinitdata = { .type = SND_AK4524, .num_dacs = 2, @@ -165,684 +124,6 @@ static unsigned char phase22_eeprom[] __devinitdata = { 0x00, /* GPIO_STATE2 */ }; -static unsigned char phase28_eeprom[] __devinitdata = { - 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ - 0x80, /* ACLINK: I2S */ - 0xfc, /* I2S: vol, 96k, 24bit, 192k */ - 0xc3, /* SPDIF: out-en, out-int, spdif-in */ - 0xff, /* GPIO_DIR */ - 0xff, /* GPIO_DIR1 */ - 0x5f, /* GPIO_DIR2 */ - 0x00, /* GPIO_MASK */ - 0x00, /* GPIO_MASK1 */ - 0x00, /* GPIO_MASK2 */ - 0x00, /* GPIO_STATE */ - 0x00, /* GPIO_STATE1 */ - 0x00, /* GPIO_STATE2 */ -}; - -/* - * write data in the SPI mode - */ -static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits) -{ - unsigned int tmp; - int i; - - tmp = snd_ice1712_gpio_read(ice); - - snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK| - PHASE28_WM_CS)); - tmp |= PHASE28_WM_RW; - tmp &= ~cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - for (i = bits - 1; i >= 0; i--) { - tmp &= ~PHASE28_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - if (data & (1 << i)) - tmp |= PHASE28_SPI_MOSI; - else - tmp &= ~PHASE28_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - - tmp &= ~PHASE28_SPI_CLK; - tmp |= cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); -} - -/* - * get the current register value of WM codec - */ -static unsigned short wm_get(ice1712_t *ice, int reg) -{ - reg <<= 1; - return ((unsigned short)ice->akm[0].images[reg] << 8) | - ice->akm[0].images[reg + 1]; -} - -/* - * set the register value of WM codec - */ -static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val) -{ - phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16); -} - -/* - * set the register value of WM codec and remember it - */ -static void wm_put(ice1712_t *ice, int reg, unsigned short val) -{ - wm_put_nocache(ice, reg, val); - reg <<= 1; - ice->akm[0].images[reg] = val >> 8; - ice->akm[0].images[reg + 1] = val; -} - -static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master) -{ - unsigned char nvol; - - if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) - nvol = 0; - else - nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX]; - - wm_put(ice, index, nvol); - wm_put_nocache(ice, index, 0x180 | nvol); -} - -/* - * DAC mute control - */ -#define wm_pcm_mute_info phase28_mono_bool_info - -static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - - down(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; - up(&ice->gpio_mutex); - return 0; -} - -static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - unsigned short nval, oval; - int change; - - snd_ice1712_save_gpio_status(ice); - oval = wm_get(ice, WM_MUTE); - nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); - if ((change = (nval != oval))) - wm_put(ice, WM_MUTE, nval); - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * Master volume attenuation mixer control - */ -static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = WM_VOL_MAX; - return 0; -} - -static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int i; - for (i=0; i<2; i++) - ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE; - return 0; -} - -static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int ch, change = 0; - - snd_ice1712_save_gpio_status(ice); - for (ch = 0; ch < 2; ch++) { - if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) { - int dac; - ice->spec.phase28.master[ch] &= WM_VOL_MUTE; - ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch]; - for (dac = 0; dac < ice->num_total_dacs; dac += 2) - wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, - ice->spec.phase28.vol[dac + ch], - ice->spec.phase28.master[ch]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -static int __devinit phase28_init(ice1712_t *ice) -{ - static unsigned short wm_inits_phase28[] = { - /* These come first to reduce init pop noise */ - 0x1b, 0x044, /* ADC Mux (AC'97 source) */ - 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ - 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ - - 0x18, 0x000, /* All power-up */ - - 0x16, 0x122, /* I2S, normal polarity, 24bit */ - 0x17, 0x022, /* 256fs, slave mode */ - 0x00, 0, /* DAC1 analog mute */ - 0x01, 0, /* DAC2 analog mute */ - 0x02, 0, /* DAC3 analog mute */ - 0x03, 0, /* DAC4 analog mute */ - 0x04, 0, /* DAC5 analog mute */ - 0x05, 0, /* DAC6 analog mute */ - 0x06, 0, /* DAC7 analog mute */ - 0x07, 0, /* DAC8 analog mute */ - 0x08, 0x100, /* master analog mute */ - 0x09, 0xff, /* DAC1 digital full */ - 0x0a, 0xff, /* DAC2 digital full */ - 0x0b, 0xff, /* DAC3 digital full */ - 0x0c, 0xff, /* DAC4 digital full */ - 0x0d, 0xff, /* DAC5 digital full */ - 0x0e, 0xff, /* DAC6 digital full */ - 0x0f, 0xff, /* DAC7 digital full */ - 0x10, 0xff, /* DAC8 digital full */ - 0x11, 0x1ff, /* master digital full */ - 0x12, 0x000, /* phase normal */ - 0x13, 0x090, /* unmute DAC L/R */ - 0x14, 0x000, /* all unmute */ - 0x15, 0x000, /* no deemphasis, no ZFLG */ - 0x19, 0x000, /* -12dB ADC/L */ - 0x1a, 0x000, /* -12dB ADC/R */ - (unsigned short)-1 - }; - - unsigned int tmp; - akm4xxx_t *ak; - unsigned short *p; - int i; - - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - - // Initialize analog chips - ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL); - if (!ak) - return -ENOMEM; - ice->akm_codecs = 1; - - snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */ - - /* reset the wm codec as the SPI mode */ - snd_ice1712_save_gpio_status(ice); - snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL)); - - tmp = snd_ice1712_gpio_read(ice); - tmp &= ~PHASE28_WM_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_WM_CS; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_WM_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - p = wm_inits_phase28; - for (; *p != (unsigned short)-1; p += 2) - wm_put(ice, p[0], p[1]); - - snd_ice1712_restore_gpio_status(ice); - - ice->spec.phase28.master[0] = WM_VOL_MUTE; - ice->spec.phase28.master[1] = WM_VOL_MUTE; - for (i = 0; i < ice->num_total_dacs; i++) { - ice->spec.phase28.vol[i] = WM_VOL_MUTE; - wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]); - } - - return 0; -} - -/* - * DAC volume attenuation mixer control - */ -static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - int voices = kcontrol->private_value >> 8; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = voices; - uinfo->value.integer.min = 0; /* mute (-101dB) */ - uinfo->value.integer.max = 0x7F; /* 0dB */ - return 0; -} - -static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int i, ofs, voices; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE; - return 0; -} - -static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int i, idx, ofs, voices; - int change = 0; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < voices; i++) { - idx = WM_DAC_ATTEN + ofs + i; - if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) { - ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE; - ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i]; - wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i], - ice->spec.phase28.master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * WM8770 mute control - */ -static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = kcontrol->private_value >> 8; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int voices, ofs, i; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xFF; - - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; - return 0; -} - -static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int change = 0, voices, ofs, i; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xFF; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < voices; i++) { - int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; - if (ucontrol->value.integer.value[i] != val) { - ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE; - ice->spec.phase28.vol[ofs + i] |= - ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; - wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i], - ice->spec.phase28.master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * WM8770 master mute control - */ -static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1; - ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1; - return 0; -} - -static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int change = 0, i; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < 2; i++) { - int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1; - if (ucontrol->value.integer.value[i] != val) { - int dac; - ice->spec.phase28.master[i] &= ~WM_VOL_MUTE; - ice->spec.phase28.master[i] |= - ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; - for (dac = 0; dac < ice->num_total_dacs; dac += 2) - wm_set_vol(ice, WM_DAC_ATTEN + dac + i, - ice->spec.phase28.vol[dac + i], - ice->spec.phase28.master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* digital master volume */ -#define PCM_0dB 0xff -#define PCM_RES 128 /* -64dB */ -#define PCM_MIN (PCM_0dB - PCM_RES) -static int wm_pcm_vol_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; /* mute (-64dB) */ - uinfo->value.integer.max = PCM_RES; /* 0dB */ - return 0; -} - -static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - - down(&ice->gpio_mutex); - val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; - val = val > PCM_MIN ? (val - PCM_MIN) : 0; - ucontrol->value.integer.value[0] = val; - up(&ice->gpio_mutex); - return 0; -} - -static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change = 0; - - snd_ice1712_save_gpio_status(ice); - nvol = ucontrol->value.integer.value[0]; - nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; - ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; - if (ovol != nvol) { - wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ - wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */ - change = 1; - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - */ -static int phase28_mono_bool_info(snd_kcontrol_t *k, 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; -} - -/* - * Deemphasis - */ -#define phase28_deemp_info phase28_mono_bool_info - -static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf; - return 0; -} - -static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - int temp, temp2; - temp2 = temp = wm_get(ice, WM_DAC_CTRL2); - if (ucontrol->value.integer.value[0]) - temp |= 0xf; - else - temp &= ~0xf; - if (temp != temp2) { - wm_put(ice, WM_DAC_CTRL2, temp); - return 1; - } - return 0; -} - -/* - * ADC Oversampling - */ -static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo) -{ - static char *texts[2] = { "128x", "64x" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - 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 phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8; - return 0; -} - -static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - int temp, temp2; - ice1712_t *ice = snd_kcontrol_chip(kcontrol); - - temp2 = temp = wm_get(ice, WM_MASTER); - - if (ucontrol->value.enumerated.item[0]) - temp |= 0x8; - else - temp &= ~0x8; - - if (temp != temp2) { - wm_put(ice, WM_MASTER, temp); - return 1; - } - return 0; -} - -static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = wm_master_mute_info, - .get = wm_master_mute_get, - .put = wm_master_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = wm_master_vol_info, - .get = wm_master_vol_get, - .put = wm_master_vol_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Rear Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 2 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Rear Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 2 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Center Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (1 << 8) | 4 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Center Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (1 << 8) | 4 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "LFE Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (1 << 8) | 5 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "LFE Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (1 << 8) | 5 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Side Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 6 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Side Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 6 - } -}; - -static snd_kcontrol_new_t wm_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = wm_pcm_mute_info, - .get = wm_pcm_mute_get, - .put = wm_pcm_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .info = wm_pcm_vol_info, - .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Deemphasis Switch", - .info = phase28_deemp_info, - .get = phase28_deemp_get, - .put = phase28_deemp_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Oversampling", - .info = phase28_oversampling_info, - .get = phase28_oversampling_get, - .put = phase28_oversampling_put - } -}; - -static int __devinit phase28_add_controls(ice1712_t *ice) -{ - unsigned int i, counts; - int err; - - counts = ARRAY_SIZE(phase28_dac_controls); - for (i = 0; i < counts; i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice)); - if (err < 0) - return err; - } - - for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice)); - if (err < 0) - return err; - } - - return 0; -} - struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_PHASE22, @@ -853,14 +134,5 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { .eeprom_size = sizeof(phase22_eeprom), .eeprom_data = phase22_eeprom, }, - { - .subvendor = VT1724_SUBDEVICE_PHASE28, - .name = "Terratec PHASE 28", - .model = "phase28", - .chip_init = phase28_init, - .build_controls = phase28_add_controls, - .eeprom_size = sizeof(phase28_eeprom), - .eeprom_data = phase28_eeprom, - }, { } /* terminator */ }; diff --git a/trunk/sound/pci/ice1712/phase.h b/trunk/sound/pci/ice1712/phase.h index 13e841b55488..6230cf16989f 100644 --- a/trunk/sound/pci/ice1712/phase.h +++ b/trunk/sound/pci/ice1712/phase.h @@ -24,28 +24,11 @@ * */ -#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\ - "{Terratec,Phase 28}," +#define PHASE_DEVICE_DESC "{Terratec,Phase 22}," #define VT1724_SUBDEVICE_PHASE22 0x3b155011 -#define VT1724_SUBDEVICE_PHASE28 0x3b154911 /* entry point */ extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; -/* PHASE28 GPIO bits */ -#define PHASE28_SPI_MISO (1 << 21) -#define PHASE28_WM_RESET (1 << 20) -#define PHASE28_SPI_CLK (1 << 19) -#define PHASE28_SPI_MOSI (1 << 18) -#define PHASE28_WM_RW (1 << 17) -#define PHASE28_AC97_RESET (1 << 16) -#define PHASE28_DIGITAL_SEL1 (1 << 15) -#define PHASE28_HP_SEL (1 << 14) -#define PHASE28_WM_CS (1 << 12) -#define PHASE28_AC97_COMMIT (1 << 11) -#define PHASE28_AC97_ADDR (1 << 10) -#define PHASE28_AC97_DATA_LOW (1 << 9) -#define PHASE28_AC97_DATA_HIGH (1 << 8) -#define PHASE28_AC97_DATA_MASK 0xFF #endif /* __SOUND_PHASE */ diff --git a/trunk/sound/pci/ice1712/vt1720_mobo.c b/trunk/sound/pci/ice1712/vt1720_mobo.c index ab61e383024f..3bd92627231c 100644 --- a/trunk/sound/pci/ice1712/vt1720_mobo.c +++ b/trunk/sound/pci/ice1712/vt1720_mobo.c @@ -110,15 +110,6 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { .eeprom_size = sizeof(k8x800_eeprom), .eeprom_data = k8x800_eeprom, }, - { - .subvendor = VT1720_SUBDEVICE_SN25P, - .name = "Shuttle SN25P", - /* identical with k8x800 */ - .chip_init = k8x800_init, - .build_controls = k8x800_add_controls, - .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = k8x800_eeprom, - }, { } /* terminator */ }; diff --git a/trunk/sound/pci/ice1712/vt1720_mobo.h b/trunk/sound/pci/ice1712/vt1720_mobo.h index 0b1b0ee1bea7..f949eb804cae 100644 --- a/trunk/sound/pci/ice1712/vt1720_mobo.h +++ b/trunk/sound/pci/ice1712/vt1720_mobo.h @@ -27,14 +27,12 @@ #define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\ "{Chaintech,ZNF3-150},"\ "{Chaintech,ZNF3-250},"\ - "{Chaintech,9CJS},"\ - "{Shuttle,SN25P}," + "{Chaintech,9CJS}," #define VT1720_SUBDEVICE_K8X800 0xf217052c #define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6 #define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6 #define VT1720_SUBDEVICE_9CJS 0x0f272327 -#define VT1720_SUBDEVICE_SN25P 0x97123650 extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; diff --git a/trunk/sound/pci/intel8x0.c b/trunk/sound/pci/intel8x0.c index cc16f95f9cef..8b33b12fa5dc 100644 --- a/trunk/sound/pci/intel8x0.c +++ b/trunk/sound/pci/intel8x0.c @@ -1725,235 +1725,229 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = { static struct ac97_quirk ac97_quirks[] __devinitdata = { { - .subvendor = 0x0e11, - .subdevice = 0x008a, + .vendor = 0x0e11, + .device = 0x008a, .name = "Compaq Evo W4000", /* AD1885 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x0e11, - .subdevice = 0x00b8, + .vendor = 0x0e11, + .device = 0x00b8, .name = "Compaq Evo D510C", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x0e11, - .subdevice = 0x0860, + .vendor = 0x0e11, + .device = 0x0860, .name = "HP/Compaq nx7010", .type = AC97_TUNE_MUTE_LED }, { - .subvendor = 0x1014, - .subdevice = 0x1f00, + .vendor = 0x1014, + .device = 0x1f00, .name = "MS-9128", .type = AC97_TUNE_ALC_JACK }, { - .subvendor = 0x1028, - .subdevice = 0x00d8, + .vendor = 0x1028, + .device = 0x00d8, .name = "Dell Precision 530", /* AD1885 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1028, - .subdevice = 0x010d, + .vendor = 0x1028, + .device = 0x010d, .name = "Dell", /* which model? AD1885 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1028, - .subdevice = 0x0126, + .vendor = 0x1028, + .device = 0x0126, .name = "Dell Optiplex GX260", /* AD1981A */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1028, - .subdevice = 0x012c, + .vendor = 0x1028, + .device = 0x012c, .name = "Dell Precision 650", /* AD1981A */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1028, - .subdevice = 0x012d, + .vendor = 0x1028, + .device = 0x012d, .name = "Dell Precision 450", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1028, - .subdevice = 0x0147, + .vendor = 0x1028, + .device = 0x0147, .name = "Dell", /* which model? AD1981B*/ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1028, - .subdevice = 0x0163, + .vendor = 0x1028, + .device = 0x0163, .name = "Dell Unknown", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x103c, - .subdevice = 0x006d, + .vendor = 0x103c, + .device = 0x006d, .name = "HP zv5000", .type = AC97_TUNE_MUTE_LED /*AD1981B*/ }, { /* FIXME: which codec? */ - .subvendor = 0x103c, - .subdevice = 0x00c3, + .vendor = 0x103c, + .device = 0x00c3, .name = "HP xw6000", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x103c, - .subdevice = 0x088c, + .vendor = 0x103c, + .device = 0x088c, .name = "HP nc8000", .type = AC97_TUNE_MUTE_LED }, { - .subvendor = 0x103c, - .subdevice = 0x0890, + .vendor = 0x103c, + .device = 0x0890, .name = "HP nc6000", .type = AC97_TUNE_MUTE_LED }, { - .subvendor = 0x103c, - .subdevice = 0x129d, + .vendor = 0x103c, + .device = 0x129d, .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x103c, - .subdevice = 0x12f1, + .vendor = 0x103c, + .device = 0x12f1, .name = "HP xw8200", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x103c, - .subdevice = 0x12f2, + .vendor = 0x103c, + .device = 0x12f2, .name = "HP xw6200", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x103c, - .subdevice = 0x3008, + .vendor = 0x103c, + .device = 0x3008, .name = "HP xw4200", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x104d, - .subdevice = 0x8197, + .vendor = 0x104d, + .device = 0x8197, .name = "Sony S1XP", .type = AC97_TUNE_INV_EAPD }, { - .subvendor = 0x1043, - .subdevice = 0x80f3, + .vendor = 0x1043, + .device = 0x80f3, .name = "ASUS ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { - .subvendor = 0x10cf, - .subdevice = 0x11c3, + .vendor = 0x10cf, + .device = 0x11c3, .name = "Fujitsu-Siemens E4010", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x10cf, - .subdevice = 0x1225, - .name = "Fujitsu-Siemens T3010", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x1253, + .vendor = 0x10cf, + .device = 0x1253, .name = "Fujitsu S6210", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x10f1, - .subdevice = 0x2665, + .vendor = 0x10f1, + .device = 0x2665, .name = "Fujitsu-Siemens Celsius", /* AD1981? */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x10f1, - .subdevice = 0x2885, + .vendor = 0x10f1, + .device = 0x2885, .name = "AMD64 Mobo", /* ALC650 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x110a, - .subdevice = 0x0056, + .vendor = 0x110a, + .device = 0x0056, .name = "Fujitsu-Siemens Scenic", /* AD1981? */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x11d4, - .subdevice = 0x5375, + .vendor = 0x11d4, + .device = 0x5375, .name = "ADI AD1985 (discrete)", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1462, - .subdevice = 0x5470, + .vendor = 0x1462, + .device = 0x5470, .name = "MSI P4 ATX 645 Ultra", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1734, - .subdevice = 0x0088, + .vendor = 0x1734, + .device = 0x0088, .name = "Fujitsu-Siemens D1522", /* AD1981 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x8086, - .subdevice = 0x2000, + .vendor = 0x8086, + .device = 0x2000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { - .subvendor = 0x8086, - .subdevice = 0x4000, + .vendor = 0x8086, + .device = 0x4000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { - .subvendor = 0x8086, - .subdevice = 0x4856, + .vendor = 0x8086, + .device = 0x4856, .name = "Intel D845WN (82801BA)", .type = AC97_TUNE_SWAP_HP }, { - .subvendor = 0x8086, - .subdevice = 0x4d44, + .vendor = 0x8086, + .device = 0x4d44, .name = "Intel D850EMV2", /* AD1885 */ .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x8086, - .subdevice = 0x4d56, + .vendor = 0x8086, + .device = 0x4d56, .name = "Intel ICH/AD1885", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x8086, - .subdevice = 0x6000, + .vendor = 0x8086, + .device = 0x6000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { - .subvendor = 0x8086, - .subdevice = 0xe000, + .vendor = 0x8086, + .device = 0xe000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, #if 0 /* FIXME: this seems wrong on most boards */ { - .subvendor = 0x8086, - .subdevice = 0xa000, + .vendor = 0x8086, + .device = 0xa000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_HP_ONLY @@ -2855,7 +2849,7 @@ static struct pci_driver driver = { static int __init alsa_card_intel8x0_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_intel8x0_exit(void) diff --git a/trunk/sound/pci/intel8x0m.c b/trunk/sound/pci/intel8x0m.c index bb758c77d211..67da096d659b 100644 --- a/trunk/sound/pci/intel8x0m.c +++ b/trunk/sound/pci/intel8x0m.c @@ -35,6 +35,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Jaroslav Kysela "); @@ -291,9 +292,60 @@ static struct pci_device_id snd_intel8x0m_ids[] = { #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 */ @@ -448,8 +500,6 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, res = 0xffff; } } - if (reg == AC97_GPIO_STATUS) - iagetword(chip, 0); /* clear semaphore */ return res; } @@ -648,6 +698,21 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea return bytes_to_frames(substream->runtime, ptr); } +static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd) +{ + /* hook off/on on start/stop */ + /* Moved this to mixer control */ + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + break; + case SNDRV_PCM_TRIGGER_STOP: + break; + default: + return -EINVAL; + } + return snd_intel8x0_pcm_trigger(substream,cmd); +} + static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream) { intel8x0_t *chip = snd_pcm_substream_chip(substream); @@ -743,7 +808,7 @@ static snd_pcm_ops_t snd_intel8x0m_playback_ops = { .hw_params = snd_intel8x0_hw_params, .hw_free = snd_intel8x0_hw_free, .prepare = snd_intel8x0m_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, + .trigger = snd_intel8x0m_pcm_trigger, .pointer = snd_intel8x0_pcm_pointer, }; @@ -754,7 +819,7 @@ static snd_pcm_ops_t snd_intel8x0m_capture_ops = { .hw_params = snd_intel8x0_hw_params, .hw_free = snd_intel8x0_hw_free, .prepare = snd_intel8x0m_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, + .trigger = snd_intel8x0m_pcm_trigger, .pointer = snd_intel8x0_pcm_pointer, }; @@ -882,6 +947,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) 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, @@ -917,6 +983,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) 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; @@ -1380,7 +1450,7 @@ static struct pci_driver driver = { static int __init alsa_card_intel8x0m_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_intel8x0m_exit(void) diff --git a/trunk/sound/pci/korg1212/korg1212.c b/trunk/sound/pci/korg1212/korg1212.c index 79d8eda54f0d..bb1de2008176 100644 --- a/trunk/sound/pci/korg1212/korg1212.c +++ b/trunk/sound/pci/korg1212/korg1212.c @@ -2541,7 +2541,7 @@ static struct pci_driver driver = { static int __init alsa_card_korg1212_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_korg1212_exit(void) diff --git a/trunk/sound/pci/maestro3.c b/trunk/sound/pci/maestro3.c index 096f15132853..2cf33083d7cc 100644 --- a/trunk/sound/pci/maestro3.c +++ b/trunk/sound/pci/maestro3.c @@ -779,12 +779,6 @@ struct m3_quirk { (e.g. for IrDA on Dell Inspirons) */ }; -struct m3_hv_quirk { - u16 vendor, device, subsystem_vendor, subsystem_device; - u32 config; /* ALLEGRO_CONFIG hardware volume bits */ - int is_omnibook; /* Do HP OmniBook GPIO magic? */ -}; - struct m3_list { int curlen; int mem_addr; @@ -834,7 +828,6 @@ struct snd_m3 { struct pci_dev *pci; struct m3_quirk *quirk; - struct m3_hv_quirk *hv_quirk; int dacs_active; int timer_users; @@ -858,11 +851,6 @@ struct snd_m3 { m3_dma_t *substreams; spinlock_t reg_lock; - spinlock_t ac97_lock; - - snd_kcontrol_t *master_switch; - snd_kcontrol_t *master_volume; - struct tasklet_struct hwvol_tq; #ifdef CONFIG_PM u16 *suspend_mem; @@ -980,71 +968,6 @@ static struct m3_quirk m3_quirk_list[] = { { NULL } }; -/* These values came from the Windows driver. */ -static struct m3_hv_quirk m3_hv_quirk_list[] = { - /* Allegro chips */ - { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, - { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */ - { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 }, - /* Maestro3 chips */ - { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */ - { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */ - { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 }, - { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, - { 0 } -}; /* * lowlevel functions @@ -1642,68 +1565,6 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s) } } -static void snd_m3_update_hw_volume(unsigned long private_data) -{ - m3_t *chip = (m3_t *) private_data; - int x, val; - unsigned long flags; - - /* Figure out which volume control button was pushed, - based on differences from the default register - values. */ - x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee; - - /* Reset the volume control registers. */ - outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE); - outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE); - outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); - outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER); - - if (!chip->master_switch || !chip->master_volume) - return; - - /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ - spin_lock_irqsave(&chip->ac97_lock, flags); - - val = chip->ac97->regs[AC97_MASTER_VOL]; - switch (x) { - case 0x88: - /* mute */ - val ^= 0x8000; - chip->ac97->regs[AC97_MASTER_VOL] = val; - outw(val, chip->iobase + CODEC_DATA); - outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); - break; - case 0xaa: - /* volume up */ - if ((val & 0x7f) > 0) - val--; - if ((val & 0x7f00) > 0) - val -= 0x0100; - chip->ac97->regs[AC97_MASTER_VOL] = val; - outw(val, chip->iobase + CODEC_DATA); - outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - break; - case 0x66: - /* volume down */ - if ((val & 0x7f) < 0x1f) - val++; - if ((val & 0x7f00) < 0x1f00) - val += 0x0100; - chip->ac97->regs[AC97_MASTER_VOL] = val; - outw(val, chip->iobase + CODEC_DATA); - outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - break; - } - spin_unlock_irqrestore(&chip->ac97_lock, flags); -} - static irqreturn_t snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -1715,10 +1576,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (status == 0xff) return IRQ_NONE; - - if (status & HV_INT_PENDING) - tasklet_hi_schedule(&chip->hwvol_tq); - + /* * ack an assp int if its running * and has an int pending @@ -1747,7 +1605,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif /* ack ints */ - outb(status, chip->iobase + HOST_INT_STATUS); + snd_m3_outw(chip, HOST_INT_STATUS, status); return IRQ_HANDLED; } @@ -1984,32 +1842,24 @@ static unsigned short snd_m3_ac97_read(ac97_t *ac97, unsigned short reg) { m3_t *chip = ac97->private_data; - unsigned long flags; - unsigned short data; if (snd_m3_ac97_wait(chip)) return 0xffff; - spin_lock_irqsave(&chip->ac97_lock, flags); snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); if (snd_m3_ac97_wait(chip)) return 0xffff; - data = snd_m3_inw(chip, CODEC_DATA); - spin_unlock_irqrestore(&chip->ac97_lock, flags); - return data; + return snd_m3_inw(chip, CODEC_DATA); } static void snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) { m3_t *chip = ac97->private_data; - unsigned long flags; if (snd_m3_ac97_wait(chip)) return; - spin_lock_irqsave(&chip->ac97_lock, flags); snd_m3_outw(chip, val, CODEC_DATA); snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); - spin_unlock_irqrestore(&chip->ac97_lock, flags); } @@ -2118,7 +1968,6 @@ static int __devinit snd_m3_mixer(m3_t *chip) { ac97_bus_t *pbus; ac97_template_t ac97; - snd_ctl_elem_id_t id; int err; static ac97_bus_ops_t ops = { .write = snd_m3_ac97_write, @@ -2139,15 +1988,6 @@ static int __devinit snd_m3_mixer(m3_t *chip) schedule_timeout(HZ / 10); snd_ac97_write(chip->ac97, AC97_PCM, 0); - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, "Master Playback Switch"); - chip->master_switch = snd_ctl_find_id(chip->card, &id); - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, "Master Playback Volume"); - chip->master_volume = snd_ctl_find_id(chip->card, &id); - return 0; } @@ -2453,7 +2293,6 @@ static int snd_m3_chip_init(m3_t *chip) { struct pci_dev *pcidev = chip->pci; - unsigned long io = chip->iobase; u32 n; u16 w; u8 t; /* makes as much sense as 'n', no? */ @@ -2464,27 +2303,8 @@ snd_m3_chip_init(m3_t *chip) DISABLE_LEGACY); pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); - if (chip->hv_quirk && chip->hv_quirk->is_omnibook) { - /* - * Volume buttons on some HP OmniBook laptops don't work - * correctly. This makes them work for the most part. - * - * Volume up and down buttons on the laptop side work. - * Fn+cursor_up (volme up) works. - * Fn+cursor_down (volume down) doesn't work. - * Fn+F7 (mute) works acts as volume up. - */ - outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK); - outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION); - outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA); - outw(0xffff, io + GPIO_MASK); - } pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); - n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); - if (chip->hv_quirk) - n |= chip->hv_quirk->config; - /* For some reason we must always use reduced debounce. */ - n |= REDUCED_DEBOUNCE; + n &= REDUCED_DEBOUNCE; n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); @@ -2512,12 +2332,6 @@ snd_m3_chip_init(m3_t *chip) outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); - outb(0x00, io + HARDWARE_VOL_CTRL); - outb(0x88, io + SHADOW_MIX_REG_VOICE); - outb(0x88, io + HW_VOL_COUNTER_VOICE); - outb(0x88, io + SHADOW_MIX_REG_MASTER); - outb(0x88, io + HW_VOL_COUNTER_MASTER); - return 0; } @@ -2527,7 +2341,7 @@ snd_m3_enable_ints(m3_t *chip) unsigned long io = chip->iobase; /* TODO: MPU401 not supported yet */ - outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL); + outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL); outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, io + ASSP_CONTROL_C); } @@ -2553,7 +2367,7 @@ static int snd_m3_free(m3_t *chip) kfree(chip->substreams); } if (chip->iobase) { - outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ + snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */ } #ifdef CONFIG_PM @@ -2672,7 +2486,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, m3_t *chip; int i, err; struct m3_quirk *quirk; - struct m3_hv_quirk *hv_quirk; + u16 subsystem_vendor, subsystem_device; static snd_device_ops_t ops = { .dev_free = snd_m3_dev_free, }; @@ -2710,25 +2524,18 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; + pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); + pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); + for (quirk = m3_quirk_list; quirk->vendor; quirk++) { - if (pci->subsystem_vendor == quirk->vendor && - pci->subsystem_device == quirk->device) { + if (subsystem_vendor == quirk->vendor && + subsystem_device == quirk->device) { printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); chip->quirk = quirk; break; } } - for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) { - if (pci->vendor == hv_quirk->vendor && - pci->device == hv_quirk->device && - pci->subsystem_vendor == hv_quirk->subsystem_vendor && - pci->subsystem_device == hv_quirk->subsystem_device) { - chip->hv_quirk = hv_quirk; - break; - } - } - chip->external_amp = enable_amp; if (amp_gpio >= 0 && amp_gpio <= 0x0f) chip->amp_gpio = amp_gpio; @@ -2786,9 +2593,6 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, return err; } - spin_lock_init(&chip->ac97_lock); - tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); - if ((err = snd_m3_mixer(chip)) < 0) return err; @@ -2898,7 +2702,7 @@ static struct pci_driver driver = { static int __init alsa_card_m3_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_m3_exit(void) diff --git a/trunk/sound/pci/mixart/mixart.c b/trunk/sound/pci/mixart/mixart.c index 082c0d0f73d2..65bb0f47af2c 100644 --- a/trunk/sound/pci/mixart/mixart.c +++ b/trunk/sound/pci/mixart/mixart.c @@ -1431,7 +1431,7 @@ static struct pci_driver driver = { static int __init alsa_card_mixart_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_mixart_exit(void) diff --git a/trunk/sound/pci/nm256/nm256.c b/trunk/sound/pci/nm256/nm256.c index 8a52091f8552..356fbeac6f9e 100644 --- a/trunk/sound/pci/nm256/nm256.c +++ b/trunk/sound/pci/nm256/nm256.c @@ -1645,7 +1645,7 @@ static struct pci_driver driver = { static int __init alsa_card_nm256_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_nm256_exit(void) diff --git a/trunk/sound/pci/rme32.c b/trunk/sound/pci/rme32.c index b7b554df6705..b96acd5a57db 100644 --- a/trunk/sound/pci/rme32.c +++ b/trunk/sound/pci/rme32.c @@ -2031,7 +2031,7 @@ static struct pci_driver driver = { static int __init alsa_card_rme32_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_rme32_exit(void) diff --git a/trunk/sound/pci/rme96.c b/trunk/sound/pci/rme96.c index 10c4f45a913c..8e2666841d21 100644 --- a/trunk/sound/pci/rme96.c +++ b/trunk/sound/pci/rme96.c @@ -2437,7 +2437,7 @@ static struct pci_driver driver = { static int __init alsa_card_rme96_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_rme96_exit(void) diff --git a/trunk/sound/pci/rme9652/Makefile b/trunk/sound/pci/rme9652/Makefile index d2c294e136f9..917374c9cd40 100644 --- a/trunk/sound/pci/rme9652/Makefile +++ b/trunk/sound/pci/rme9652/Makefile @@ -5,9 +5,7 @@ snd-rme9652-objs := rme9652.o snd-hdsp-objs := hdsp.o -snd-hdspm-objs := hdspm.o # Toplevel Module Dependency obj-$(CONFIG_SND_RME9652) += snd-rme9652.o obj-$(CONFIG_SND_HDSP) += snd-hdsp.o -obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o diff --git a/trunk/sound/pci/rme9652/hdsp.c b/trunk/sound/pci/rme9652/hdsp.c index a673cc438b91..12efbf0fab54 100644 --- a/trunk/sound/pci/rme9652/hdsp.c +++ b/trunk/sound/pci/rme9652/hdsp.c @@ -559,22 +559,18 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer { dmab->dev.type = SNDRV_DMA_TYPE_DEV; dmab->dev.dev = snd_dma_pci_data(pci); - if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { - if (dmab->bytes >= size) - return 0; + if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), + size, dmab) < 0) + return -ENOMEM; } - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, dmab) < 0) - return -ENOMEM; return 0; } static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) { - if (dmab->area) { - dmab->dev.dev = NULL; /* make it anonymous */ + if (dmab->area) snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); - } } @@ -4916,9 +4912,19 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp) release_firmware(fw); return -EINVAL; } - +#ifdef SNDRV_BIG_ENDIAN + { + int i; + 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) | + ((*src & 0x00ff0000) >> 8) | + ((*src & 0xff000000) >> 16); + } +#else memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); - +#endif release_firmware(fw); hdsp->state |= HDSP_FirmwareCached; @@ -5188,7 +5194,7 @@ static struct pci_driver driver = { static int __init alsa_card_hdsp_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_hdsp_exit(void) diff --git a/trunk/sound/pci/rme9652/hdspm.c b/trunk/sound/pci/rme9652/hdspm.c deleted file mode 100644 index 9e86d0eb41ce..000000000000 --- a/trunk/sound/pci/rme9652/hdspm.c +++ /dev/null @@ -1,3671 +0,0 @@ -/* -*- linux-c -*- - * - * ALSA driver for RME Hammerfall DSP MADI audio interface(s) - * - * Copyright (c) 2003 Winfried Ritsch (IEM) - * code based on hdsp.c Paul Davis - * Marcus Andersson - * Thomas Charbonnel - * - * 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 -#include -#include -#include -#include - -#include - -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 */ - -/* Disable precise pointer at start */ -static int precise_ptr[SNDRV_CARDS]; - -/* Send all playback to line outs */ -static int line_outs_monitor[SNDRV_CARDS]; - -/* Enable Analog Outs on Channel 63/64 by default */ -static int enable_monitor[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); - -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for RME HDSPM interface."); - -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); - -module_param_array(precise_ptr, bool, NULL, 0444); -MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable."); - -module_param_array(line_outs_monitor, bool, NULL, 0444); -MODULE_PARM_DESC(line_outs_monitor, - "Send playback streams to analog outs by default."); - -module_param_array(enable_monitor, bool, NULL, 0444); -MODULE_PARM_DESC(enable_monitor, - "Enable Analog Out on Channel 63/64 by default."); - -MODULE_AUTHOR - ("Winfried Ritsch , Paul Davis , " - "Marcus Andersson, Thomas Charbonnel "); -MODULE_DESCRIPTION("RME HDSPM"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); - -/* --- Write registers. --- - These are defined as byte-offsets from the iobase value. */ - -#define HDSPM_controlRegister 64 -#define HDSPM_interruptConfirmation 96 -#define HDSPM_control2Reg 256 /* not in specs ???????? */ -#define HDSPM_midiDataOut0 352 /* just believe in old code */ -#define HDSPM_midiDataOut1 356 - -/* DMA enable for 64 channels, only Bit 0 is relevant */ -#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ -#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ - -/* 16 page addresses for each of the 64 channels DMA buffer in and out - (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ -#define HDSPM_pageAddressBufferOut 8192 -#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) - -#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */ - -#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */ - -/* --- Read registers. --- - These are defined as byte-offsets from the iobase value */ -#define HDSPM_statusRegister 0 -#define HDSPM_statusRegister2 96 - -#define HDSPM_midiDataIn0 360 -#define HDSPM_midiDataIn1 364 - -/* status is data bytes in MIDI-FIFO (0-128) */ -#define HDSPM_midiStatusOut0 384 -#define HDSPM_midiStatusOut1 388 -#define HDSPM_midiStatusIn0 392 -#define HDSPM_midiStatusIn1 396 - - -/* the meters are regular i/o-mapped registers, but offset - considerably from the rest. the peak registers are reset - when read; the least-significant 4 bits are full-scale counters; - the actual peak value is in the most-significant 24 bits. -*/ -#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */ - -/* --- Control Register bits --------- */ -#define HDSPM_Start (1<<0) /* start engine */ - -#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */ -#define HDSPM_Latency1 (1<<2) /* where n is defined */ -#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ - -#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */ - -#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ - -#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */ -#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */ -#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ -#define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */ - -#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, - 56channelMODE=0 */ - -#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, - 0=off, 1=on */ - -#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ -#define HDSPM_InputSelect1 (1<<15) /* should be 0 */ - -#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ -#define HDSPM_SyncRef1 (1<<17) /* should be 0 */ - -#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use - AES additional bits in - lower 5 Audiodatabits ??? */ - -#define HDSPM_Midi0InterruptEnable (1<<22) -#define HDSPM_Midi1InterruptEnable (1<<23) - -#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ - - -/* --- bit helper defines */ -#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) -#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1) -#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) -#define HDSPM_InputOptical 0 -#define HDSPM_InputCoaxial (HDSPM_InputSelect0) -#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1) -#define HDSPM_SyncRef_Word 0 -#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) - -#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ -#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ - -#define HDSPM_Frequency32KHz HDSPM_Frequency0 -#define HDSPM_Frequency44_1KHz HDSPM_Frequency1 -#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) -#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) -#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) -#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) - -/* --- for internal discrimination */ -#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ -#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1 -#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2 -#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3 -#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4 -#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5 -#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6 -#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7 -#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8 -#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9 - -/* Synccheck Status */ -#define HDSPM_SYNC_CHECK_NO_LOCK 0 -#define HDSPM_SYNC_CHECK_LOCK 1 -#define HDSPM_SYNC_CHECK_SYNC 2 - -/* AutoSync References - used by "autosync_ref" control switch */ -#define HDSPM_AUTOSYNC_FROM_WORD 0 -#define HDSPM_AUTOSYNC_FROM_MADI 1 -#define HDSPM_AUTOSYNC_FROM_NONE 2 - -/* Possible sources of MADI input */ -#define HDSPM_OPTICAL 0 /* optical */ -#define HDSPM_COAXIAL 1 /* BNC */ - -#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) -#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1) - -#define hdspm_encode_in(x) (((x)&0x3)<<14) -#define hdspm_decode_in(x) (((x)>>14)&0x3) - -/* --- control2 register bits --- */ -#define HDSPM_TMS (1<<0) -#define HDSPM_TCK (1<<1) -#define HDSPM_TDI (1<<2) -#define HDSPM_JTAG (1<<3) -#define HDSPM_PWDN (1<<4) -#define HDSPM_PROGRAM (1<<5) -#define HDSPM_CONFIG_MODE_0 (1<<6) -#define HDSPM_CONFIG_MODE_1 (1<<7) -/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/ -#define HDSPM_BIGENDIAN_MODE (1<<9) -#define HDSPM_RD_MULTIPLE (1<<10) - -/* --- Status Register bits --- */ -#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ -#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ -#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ -#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ - -#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ - /* since 64byte accurate last 6 bits - are not used */ - -#define HDSPM_madiSync (1<<18) /* MADI is in sync */ -#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ - -#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ -#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */ -#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ -#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ - -#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */ -#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ -#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ - -/* --- status bit helpers */ -#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3) -#define HDSPM_madiFreq32 (HDSPM_madiFreq0) -#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) -#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) -#define HDSPM_madiFreq64 (HDSPM_madiFreq2) -#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2) -#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2) -#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2) -#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3) -#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0) - -/* Status2 Register bits */ - -#define HDSPM_version0 (1<<0) /* not realy defined but I guess */ -#define HDSPM_version1 (1<<1) /* in former cards it was ??? */ -#define HDSPM_version2 (1<<2) - -#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */ -#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */ - -#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */ -#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */ -#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ -/* missing Bit for 111=128, 1000=176.4, 1001=192 */ - -#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */ -#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ -#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ - -#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync) - -#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2) -#define HDSPM_wcFreq32 (HDSPM_wc_freq0) -#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1) -#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1) -#define HDSPM_wcFreq64 (HDSPM_wc_freq2) -#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) -#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) - - -#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) -#define HDSPM_SelSyncRef_WORD 0 -#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) -#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) - -/* Mixer Values */ -#define UNITY_GAIN 32768 /* = 65536/2 */ -#define MINUS_INFINITY_GAIN 0 - -/* PCI info */ -#ifndef PCI_VENDOR_ID_XILINX -#define PCI_VENDOR_ID_XILINX 0x10ee -#endif -#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP -#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 -#endif -#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI -#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 -#endif - - -/* Number of channels for different Speed Modes */ -#define MADI_SS_CHANNELS 64 -#define MADI_DS_CHANNELS 32 -#define MADI_QS_CHANNELS 16 - -/* the size of a substream (1 mono data stream) */ -#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) -#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) - -/* the size of the area we need to allocate for DMA transfers. the - size is the same regardless of the number of channels, and - also the latency to use. - for one direction !!! -*/ -#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) -#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) - -typedef struct _hdspm hdspm_t; -typedef struct _hdspm_midi hdspm_midi_t; - -struct _hdspm_midi { - hdspm_t *hdspm; - int id; - snd_rawmidi_t *rmidi; - snd_rawmidi_substream_t *input; - snd_rawmidi_substream_t *output; - char istimer; /* timer in use */ - struct timer_list timer; - spinlock_t lock; - int pending; -}; - -struct _hdspm { - spinlock_t lock; - snd_pcm_substream_t *capture_substream; /* only one playback */ - snd_pcm_substream_t *playback_substream; /* and/or capture stream */ - - char *card_name; /* for procinfo */ - unsigned short firmware_rev; /* dont know if relevant */ - - int precise_ptr; /* use precise pointers, to be tested */ - int monitor_outs; /* set up monitoring outs init flag */ - - u32 control_register; /* cached value */ - u32 control2_register; /* cached value */ - - hdspm_midi_t midi[2]; - struct tasklet_struct midi_tasklet; - - size_t period_bytes; - unsigned char ss_channels; /* channels of card in single speed */ - unsigned char ds_channels; /* Double Speed */ - unsigned char qs_channels; /* Quad Speed */ - - unsigned char *playback_buffer; /* suitably aligned address */ - unsigned char *capture_buffer; /* suitably aligned address */ - - pid_t capture_pid; /* process id which uses capture */ - pid_t playback_pid; /* process id which uses capture */ - int running; /* running status */ - - int last_external_sample_rate; /* samplerate mystic ... */ - int last_internal_sample_rate; - int system_sample_rate; - - char *channel_map; /* channel map for DS and Quadspeed */ - - int dev; /* Hardware vars... */ - int irq; - unsigned long port; - void __iomem *iobase; - - int irq_count; /* for debug */ - - snd_card_t *card; /* one card */ - snd_pcm_t *pcm; /* has one pcm */ - snd_hwdep_t *hwdep; /* and a hwdep for additional ioctl */ - struct pci_dev *pci; /* and an pci info */ - - /* Mixer vars */ - snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */ - snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */ - hdspm_mixer_t *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */ - -}; - -/* These tables map the ALSA channels 1..N to the channels that we - need to use in order to find the relevant channel buffer. RME - refer to this kind of mapping as between "the ADAT channel and - the DMA channel." We index it using the logical audio channel, - and the value is the DMA channel (i.e. channel buffer number) - where the data for that channel can be read/written from/to. -*/ - -static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 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, 63 -}; - -static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = { - 0, 2, 4, 6, 8, 10, 12, 14, - 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, - 48, 50, 52, 54, 56, 58, 60, 62, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = { - 0, 4, 8, 12, 16, 20, 24, 28, - 32, 36, 40, 44, 48, 52, 56, 60 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - - -static struct pci_device_id snd_hdspm_ids[] = { - { - .vendor = PCI_VENDOR_ID_XILINX, - .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .class = 0, - .class_mask = 0, - .driver_data = 0}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, snd_hdspm_ids); - -/* prototypes */ -static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card, - hdspm_t * hdspm); -static int __devinit snd_hdspm_create_pcm(snd_card_t * card, - hdspm_t * hdspm); - -static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm); -static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm); -static int hdspm_autosync_ref(hdspm_t * hdspm); -static int snd_hdspm_set_defaults(hdspm_t * hdspm); -static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf, - unsigned int reg, int channels); - -/* Write/read to/from HDSPM with Adresses in Bytes - not words but only 32Bit writes are allowed */ - -static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg, - unsigned int val) -{ - writel(val, hdspm->iobase + reg); -} - -static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg) -{ - return readl(hdspm->iobase + reg); -} - -/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader - mixer is write only on hardware so we have to cache him for read - each fader is a u32, but uses only the first 16 bit */ - -static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan, - unsigned int in) -{ - if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS) - return 0; - - return hdspm->mixer->ch[chan].in[in]; -} - -static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan, - unsigned int pb) -{ - if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS) - return 0; - return hdspm->mixer->ch[chan].pb[pb]; -} - -static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan, - unsigned int in, unsigned short data) -{ - if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS) - return -1; - - hdspm_write(hdspm, - HDSPM_MADI_mixerBase + - ((in + 128 * chan) * sizeof(u32)), - (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF)); - return 0; -} - -static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan, - unsigned int pb, unsigned short data) -{ - if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS) - return -1; - - hdspm_write(hdspm, - HDSPM_MADI_mixerBase + - ((64 + pb + 128 * chan) * sizeof(u32)), - (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF)); - return 0; -} - - -/* enable DMA for specific channels, now available for DSP-MADI */ -static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v) -{ - hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v); -} - -static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v) -{ - hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v); -} - -/* check if same process is writing and reading */ -static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm) -{ - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&hdspm->lock, flags); - if ((hdspm->playback_pid != hdspm->capture_pid) && - (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) { - ret = 0; - } - spin_unlock_irqrestore(&hdspm->lock, flags); - return ret; -} - -/* check for external sample rate */ -static inline int hdspm_external_sample_rate(hdspm_t * hdspm) -{ - unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); - unsigned int rate_bits; - int rate = 0; - - /* if wordclock has synced freq and wordclock is valid */ - if ((status2 & HDSPM_wcLock) != 0 && - (status & HDSPM_SelSyncRef0) == 0) { - - rate_bits = status2 & HDSPM_wcFreqMask; - - switch (rate_bits) { - case HDSPM_wcFreq32: - rate = 32000; - break; - case HDSPM_wcFreq44_1: - rate = 44100; - break; - case HDSPM_wcFreq48: - rate = 48000; - break; - case HDSPM_wcFreq64: - rate = 64000; - break; - case HDSPM_wcFreq88_2: - rate = 88200; - break; - case HDSPM_wcFreq96: - rate = 96000; - break; - /* Quadspeed Bit missing ???? */ - default: - rate = 0; - break; - } - } - - /* if rate detected and Syncref is Word than have it, word has priority to MADI */ - if (rate != 0 - && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) - return rate; - - /* maby a madi input (which is taken if sel sync is madi) */ - if (status & HDSPM_madiLock) { - rate_bits = status & HDSPM_madiFreqMask; - - switch (rate_bits) { - case HDSPM_madiFreq32: - rate = 32000; - break; - case HDSPM_madiFreq44_1: - rate = 44100; - break; - case HDSPM_madiFreq48: - rate = 48000; - break; - case HDSPM_madiFreq64: - rate = 64000; - break; - case HDSPM_madiFreq88_2: - rate = 88200; - break; - case HDSPM_madiFreq96: - rate = 96000; - break; - case HDSPM_madiFreq128: - rate = 128000; - break; - case HDSPM_madiFreq176_4: - rate = 176400; - break; - case HDSPM_madiFreq192: - rate = 192000; - break; - default: - rate = 0; - break; - } - } - return rate; -} - -/* Latency function */ -static inline void hdspm_compute_period_size(hdspm_t * hdspm) -{ - hdspm->period_bytes = - 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); -} - -static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm) -{ - int position; - - position = hdspm_read(hdspm, HDSPM_statusRegister); - - if (!hdspm->precise_ptr) { - return (position & HDSPM_BufferID) ? (hdspm->period_bytes / - 4) : 0; - } - - /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst) - i have experimented that it is at most 64 Byte to much for playing - so substraction of 64 byte should be ok for ALSA, but use it only - for application where you know what you do since if you come to - near with record pointer it can be a disaster */ - - position &= HDSPM_BufferPositionMask; - position = ((position - 64) % (2 * hdspm->period_bytes)) / 4; - - return position; -} - - -static inline void hdspm_start_audio(hdspm_t * s) -{ - s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start); - hdspm_write(s, HDSPM_controlRegister, s->control_register); -} - -static inline void hdspm_stop_audio(hdspm_t * s) -{ - s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable); - hdspm_write(s, HDSPM_controlRegister, s->control_register); -} - -/* should I silence all or only opened ones ? doit all for first even is 4MB*/ -static inline void hdspm_silence_playback(hdspm_t * hdspm) -{ - int i; - int n = hdspm->period_bytes; - void *buf = hdspm->playback_buffer; - - snd_assert(buf != NULL, return); - - for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { - memset(buf, 0, n); - buf += HDSPM_CHANNEL_BUFFER_BYTES; - } -} - -static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames) -{ - int n; - - spin_lock_irq(&s->lock); - - frames >>= 7; - n = 0; - while (frames) { - n++; - frames >>= 1; - } - s->control_register &= ~HDSPM_LatencyMask; - s->control_register |= hdspm_encode_latency(n); - - hdspm_write(s, HDSPM_controlRegister, s->control_register); - - hdspm_compute_period_size(s); - - spin_unlock_irq(&s->lock); - - return 0; -} - - -/* dummy set rate lets see what happens */ -static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally) -{ - int reject_if_open = 0; - int current_rate; - int rate_bits; - int not_set = 0; - - /* ASSUMPTION: hdspm->lock is either set, or there is no need for - it (e.g. during module initialization). - */ - - if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { - - /* SLAVE --- */ - if (called_internally) { - - /* request from ctl or card initialization - just make a warning an remember setting - for future master mode switching */ - - snd_printk - (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n"); - not_set = 1; - } else { - - /* hw_param request while in AutoSync mode */ - int external_freq = - hdspm_external_sample_rate(hdspm); - - if ((hdspm_autosync_ref(hdspm) == - HDSPM_AUTOSYNC_FROM_NONE)) { - - snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n"); - not_set = 1; - - } else if (rate != external_freq) { - - snd_printk - (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n"); - not_set = 1; - } - } - } - - current_rate = hdspm->system_sample_rate; - - /* Changing between Singe, Double and Quad speed is not - allowed if any substreams are open. This is because such a change - causes a shift in the location of the DMA buffers and a reduction - in the number of available buffers. - - Note that a similar but essentially insoluble problem exists for - externally-driven rate changes. All we can do is to flag rate - changes in the read/write routines. - */ - - switch (rate) { - case 32000: - if (current_rate > 48000) { - reject_if_open = 1; - } - rate_bits = HDSPM_Frequency32KHz; - break; - case 44100: - if (current_rate > 48000) { - reject_if_open = 1; - } - rate_bits = HDSPM_Frequency44_1KHz; - break; - case 48000: - if (current_rate > 48000) { - reject_if_open = 1; - } - rate_bits = HDSPM_Frequency48KHz; - break; - case 64000: - if (current_rate <= 48000) { - reject_if_open = 1; - } - rate_bits = HDSPM_Frequency64KHz; - break; - case 88200: - if (current_rate <= 48000) { - reject_if_open = 1; - } - rate_bits = HDSPM_Frequency88_2KHz; - break; - case 96000: - if (current_rate <= 48000) { - reject_if_open = 1; - } - rate_bits = HDSPM_Frequency96KHz; - break; - default: - return -EINVAL; - } - - if (reject_if_open - && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { - snd_printk - (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n", - hdspm->capture_pid, hdspm->playback_pid); - return -EBUSY; - } - - hdspm->control_register &= ~HDSPM_FrequencyMask; - hdspm->control_register |= rate_bits; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - if (rate > 64000) - hdspm->channel_map = channel_map_madi_qs; - else if (rate > 48000) - hdspm->channel_map = channel_map_madi_ds; - else - hdspm->channel_map = channel_map_madi_ss; - - hdspm->system_sample_rate = rate; - - if (not_set != 0) - return -1; - - return 0; -} - -/* mainly for init to 0 on load */ -static void all_in_all_mixer(hdspm_t * hdspm, int sgain) -{ - int i, j; - unsigned int gain = - (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain; - - for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) - for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { - hdspm_write_in_gain(hdspm, i, j, gain); - hdspm_write_pb_gain(hdspm, i, j, gain); - } -} - -/*---------------------------------------------------------------------------- - MIDI - ----------------------------------------------------------------------------*/ - -static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id) -{ - /* the hardware already does the relevant bit-mask with 0xff */ - if (id) - return hdspm_read(hdspm, HDSPM_midiDataIn1); - else - return hdspm_read(hdspm, HDSPM_midiDataIn0); -} - -static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val) -{ - /* the hardware already does the relevant bit-mask with 0xff */ - if (id) - return hdspm_write(hdspm, HDSPM_midiDataOut1, val); - else - return hdspm_write(hdspm, HDSPM_midiDataOut0, val); -} - -static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id) -{ - if (id) - return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff); - else - return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff); -} - -static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id) -{ - int fifo_bytes_used; - - if (id) - fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff; - else - fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff; - - if (fifo_bytes_used < 128) - return 128 - fifo_bytes_used; - else - return 0; -} - -static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id) -{ - while (snd_hdspm_midi_input_available (hdspm, id)) - snd_hdspm_midi_read_byte (hdspm, id); -} - -static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi) -{ - unsigned long flags; - int n_pending; - int to_write; - int i; - unsigned char buf[128]; - - /* Output is not interrupt driven */ - - spin_lock_irqsave (&hmidi->lock, flags); - if (hmidi->output) { - if (!snd_rawmidi_transmit_empty (hmidi->output)) { - if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - - if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { - for (i = 0; i < to_write; ++i) - snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]); - } - } - } - } - spin_unlock_irqrestore (&hmidi->lock, flags); - return 0; -} - -static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi) -{ - unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ - unsigned long flags; - int n_pending; - int i; - - spin_lock_irqsave (&hmidi->lock, flags); - if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) { - if (hmidi->input) { - if (n_pending > (int)sizeof (buf)) { - n_pending = sizeof (buf); - } - for (i = 0; i < n_pending; ++i) { - buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); - } - if (n_pending) { - snd_rawmidi_receive (hmidi->input, buf, n_pending); - } - } else { - /* flush the MIDI input FIFO */ - while (n_pending--) { - snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); - } - } - } - hmidi->pending = 0; - if (hmidi->id) { - hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; - } else { - hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; - } - hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); - spin_unlock_irqrestore (&hmidi->lock, flags); - return snd_hdspm_midi_output_write (hmidi); -} - -static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up) -{ - hdspm_t *hdspm; - hdspm_midi_t *hmidi; - unsigned long flags; - u32 ie; - - hmidi = (hdspm_midi_t *) substream->rmidi->private_data; - hdspm = hmidi->hdspm; - ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; - spin_lock_irqsave (&hdspm->lock, flags); - if (up) { - if (!(hdspm->control_register & ie)) { - snd_hdspm_flush_midi_input (hdspm, hmidi->id); - hdspm->control_register |= ie; - } - } else { - hdspm->control_register &= ~ie; - } - - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - spin_unlock_irqrestore (&hdspm->lock, flags); -} - -static void snd_hdspm_midi_output_timer(unsigned long data) -{ - hdspm_midi_t *hmidi = (hdspm_midi_t *) data; - unsigned long flags; - - snd_hdspm_midi_output_write(hmidi); - spin_lock_irqsave (&hmidi->lock, flags); - - /* this does not bump hmidi->istimer, because the - kernel automatically removed the timer when it - expired, and we are now adding it back, thus - leaving istimer wherever it was set before. - */ - - if (hmidi->istimer) { - hmidi->timer.expires = 1 + jiffies; - add_timer(&hmidi->timer); - } - - spin_unlock_irqrestore (&hmidi->lock, flags); -} - -static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up) -{ - hdspm_midi_t *hmidi; - unsigned long flags; - - hmidi = (hdspm_midi_t *) substream->rmidi->private_data; - spin_lock_irqsave (&hmidi->lock, flags); - if (up) { - if (!hmidi->istimer) { - init_timer(&hmidi->timer); - hmidi->timer.function = snd_hdspm_midi_output_timer; - hmidi->timer.data = (unsigned long) hmidi; - hmidi->timer.expires = 1 + jiffies; - add_timer(&hmidi->timer); - hmidi->istimer++; - } - } else { - if (hmidi->istimer && --hmidi->istimer <= 0) { - del_timer (&hmidi->timer); - } - } - spin_unlock_irqrestore (&hmidi->lock, flags); - if (up) - snd_hdspm_midi_output_write(hmidi); -} - -static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream) -{ - hdspm_midi_t *hmidi; - - hmidi = (hdspm_midi_t *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); - hmidi->input = substream; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream) -{ - hdspm_midi_t *hmidi; - - hmidi = (hdspm_midi_t *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->output = substream; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream) -{ - hdspm_midi_t *hmidi; - - snd_hdspm_midi_input_trigger (substream, 0); - - hmidi = (hdspm_midi_t *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->input = NULL; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream) -{ - hdspm_midi_t *hmidi; - - snd_hdspm_midi_output_trigger (substream, 0); - - hmidi = (hdspm_midi_t *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->output = NULL; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -snd_rawmidi_ops_t snd_hdspm_midi_output = -{ - .open = snd_hdspm_midi_output_open, - .close = snd_hdspm_midi_output_close, - .trigger = snd_hdspm_midi_output_trigger, -}; - -snd_rawmidi_ops_t snd_hdspm_midi_input = -{ - .open = snd_hdspm_midi_input_open, - .close = snd_hdspm_midi_input_close, - .trigger = snd_hdspm_midi_input_trigger, -}; - -static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id) -{ - int err; - char buf[32]; - - hdspm->midi[id].id = id; - hdspm->midi[id].rmidi = NULL; - hdspm->midi[id].input = NULL; - hdspm->midi[id].output = NULL; - hdspm->midi[id].hdspm = hdspm; - hdspm->midi[id].istimer = 0; - hdspm->midi[id].pending = 0; - spin_lock_init (&hdspm->midi[id].lock); - - sprintf (buf, "%s MIDI %d", card->shortname, id+1); - if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0) - return err; - - sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); - hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; - - snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output); - snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input); - - hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - return 0; -} - - -static void hdspm_midi_tasklet(unsigned long arg) -{ - hdspm_t *hdspm = (hdspm_t *)arg; - - if (hdspm->midi[0].pending) - snd_hdspm_midi_input_read (&hdspm->midi[0]); - if (hdspm->midi[1].pending) - snd_hdspm_midi_input_read (&hdspm->midi[1]); -} - - -/*----------------------------------------------------------------------------- - Status Interface - ----------------------------------------------------------------------------*/ - -/* get the system sample rate which is set */ - -#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_system_sample_rate, \ - .get = snd_hdspm_get_system_sample_rate \ -} - -static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - return 0; -} - -static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * - ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate; - return 0; -} - -#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_autosync_sample_rate, \ - .get = snd_hdspm_get_autosync_sample_rate \ -} - -static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "32000", "44100", "48000", - "64000", "88200", "96000", - "128000", "176400", "192000", - "None" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 10; - 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_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * - ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - switch (hdspm_external_sample_rate(hdspm)) { - case 32000: - ucontrol->value.enumerated.item[0] = 0; - break; - case 44100: - ucontrol->value.enumerated.item[0] = 1; - break; - case 48000: - ucontrol->value.enumerated.item[0] = 2; - break; - case 64000: - ucontrol->value.enumerated.item[0] = 3; - break; - case 88200: - ucontrol->value.enumerated.item[0] = 4; - break; - case 96000: - ucontrol->value.enumerated.item[0] = 5; - break; - case 128000: - ucontrol->value.enumerated.item[0] = 6; - break; - case 176400: - ucontrol->value.enumerated.item[0] = 7; - break; - case 192000: - ucontrol->value.enumerated.item[0] = 8; - break; - - default: - ucontrol->value.enumerated.item[0] = 9; - } - return 0; -} - -#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_system_clock_mode, \ - .get = snd_hdspm_get_system_clock_mode, \ -} - - - -static int hdspm_system_clock_mode(hdspm_t * hdspm) -{ - /* Always reflect the hardware info, rme is never wrong !!!! */ - - if (hdspm->control_register & HDSPM_ClockModeMaster) - return 0; - return 1; -} - -static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "Master", "Slave" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - 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_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = - hdspm_system_clock_mode(hdspm); - return 0; -} - -#define HDSPM_CLOCK_SOURCE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_clock_source, \ - .get = snd_hdspm_get_clock_source, \ - .put = snd_hdspm_put_clock_source \ -} - -static int hdspm_clock_source(hdspm_t * hdspm) -{ - if (hdspm->control_register & HDSPM_ClockModeMaster) { - switch (hdspm->system_sample_rate) { - case 32000: - return 1; - case 44100: - return 2; - case 48000: - return 3; - case 64000: - return 4; - case 88200: - return 5; - case 96000: - return 6; - case 128000: - return 7; - case 176400: - return 8; - case 192000: - return 9; - default: - return 3; - } - } else { - return 0; - } -} - -static int hdspm_set_clock_source(hdspm_t * hdspm, int mode) -{ - int rate; - switch (mode) { - - case HDSPM_CLOCK_SOURCE_AUTOSYNC: - if (hdspm_external_sample_rate(hdspm) != 0) { - hdspm->control_register &= ~HDSPM_ClockModeMaster; - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - return 0; - } - return -1; - case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: - rate = 32000; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: - rate = 44100; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: - rate = 48000; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: - rate = 64000; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: - rate = 88200; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: - rate = 96000; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: - rate = 128000; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: - rate = 176400; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: - rate = 192000; - break; - - default: - rate = 44100; - } - hdspm->control_register |= HDSPM_ClockModeMaster; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - hdspm_set_rate(hdspm, rate, 1); - return 0; -} - -static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "AutoSync", - "Internal 32.0 kHz", "Internal 44.1 kHz", - "Internal 48.0 kHz", - "Internal 64.0 kHz", "Internal 88.2 kHz", - "Internal 96.0 kHz", - "Internal 128.0 kHz", "Internal 176.4 kHz", - "Internal 192.0 kHz" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 10; - - 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_hdspm_get_clock_source(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm); - return 0; -} - -static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) - val = 0; - if (val > 6) - val = 6; - spin_lock_irq(&hdspm->lock); - if (val != hdspm_clock_source(hdspm)) - change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_PREF_SYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_pref_sync_ref, \ - .get = snd_hdspm_get_pref_sync_ref, \ - .put = snd_hdspm_put_pref_sync_ref \ -} - -static int hdspm_pref_sync_ref(hdspm_t * hdspm) -{ - /* Notice that this looks at the requested sync source, - not the one actually in use. - */ - switch (hdspm->control_register & HDSPM_SyncRefMask) { - case HDSPM_SyncRef_Word: - return HDSPM_SYNC_FROM_WORD; - case HDSPM_SyncRef_MADI: - return HDSPM_SYNC_FROM_MADI; - } - - return HDSPM_SYNC_FROM_WORD; -} - -static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref) -{ - hdspm->control_register &= ~HDSPM_SyncRefMask; - - switch (pref) { - case HDSPM_SYNC_FROM_MADI: - hdspm->control_register |= HDSPM_SyncRef_MADI; - break; - case HDSPM_SYNC_FROM_WORD: - hdspm->control_register |= HDSPM_SyncRef_Word; - break; - default: - return -1; - } - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - return 0; -} - -static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "Word", "MADI" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - - uinfo->value.enumerated.items = 2; - - 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_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); - return 0; -} - -static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change, max; - unsigned int val; - - max = 2; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - val = ucontrol->value.enumerated.item[0] % max; - - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_pref_sync_ref(hdspm); - hdspm_set_pref_sync_ref(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_AUTOSYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_autosync_ref, \ - .get = snd_hdspm_get_autosync_ref, \ -} - -static int hdspm_autosync_ref(hdspm_t * hdspm) -{ - /* This looks at the autosync selected sync reference */ - unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - - switch (status2 & HDSPM_SelSyncRefMask) { - - case HDSPM_SelSyncRef_WORD: - return HDSPM_AUTOSYNC_FROM_WORD; - - case HDSPM_SelSyncRef_MADI: - return HDSPM_AUTOSYNC_FROM_MADI; - - case HDSPM_SelSyncRef_NVALID: - return HDSPM_AUTOSYNC_FROM_NONE; - - default: - return 0; - } - - return 0; -} - -static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "WordClock", "MADI", "None" }; - - 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_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); - return 0; -} - -#define HDSPM_LINE_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_line_out, \ - .get = snd_hdspm_get_line_out, \ - .put = snd_hdspm_put_line_out \ -} - -static int hdspm_line_out(hdspm_t * hdspm) -{ - return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0; -} - - -static int hdspm_set_line_output(hdspm_t * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_LineOut; - else - hdspm->control_register &= ~HDSPM_LineOut; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_line_out(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_hdspm_get_line_out(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_line_out(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_line_out(hdspm); - hdspm_set_line_output(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_TX_64(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_tx_64, \ - .get = snd_hdspm_get_tx_64, \ - .put = snd_hdspm_put_tx_64 \ -} - -static int hdspm_tx_64(hdspm_t * hdspm) -{ - return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0; -} - -static int hdspm_set_tx_64(hdspm_t * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_TX_64ch; - else - hdspm->control_register &= ~HDSPM_TX_64ch; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_tx_64(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_hdspm_get_tx_64(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_tx_64(hdspm); - hdspm_set_tx_64(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_C_TMS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_c_tms, \ - .get = snd_hdspm_get_c_tms, \ - .put = snd_hdspm_put_c_tms \ -} - -static int hdspm_c_tms(hdspm_t * hdspm) -{ - return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0; -} - -static int hdspm_set_c_tms(hdspm_t * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_clr_tms; - else - hdspm->control_register &= ~HDSPM_clr_tms; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_c_tms(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_hdspm_get_c_tms(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_c_tms(hdspm); - hdspm_set_c_tms(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_SAFE_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_safe_mode, \ - .get = snd_hdspm_get_safe_mode, \ - .put = snd_hdspm_put_safe_mode \ -} - -static int hdspm_safe_mode(hdspm_t * hdspm) -{ - return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0; -} - -static int hdspm_set_safe_mode(hdspm_t * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_AutoInp; - else - hdspm->control_register &= ~HDSPM_AutoInp; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_safe_mode(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_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_safe_mode(hdspm); - hdspm_set_safe_mode(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_INPUT_SELECT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_input_select, \ - .get = snd_hdspm_get_input_select, \ - .put = snd_hdspm_put_input_select \ -} - -static int hdspm_input_select(hdspm_t * hdspm) -{ - return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0; -} - -static int hdspm_set_input_select(hdspm_t * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_InputSelect0; - else - hdspm->control_register &= ~HDSPM_InputSelect0; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "optical", "coaxial" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - 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_hdspm_get_input_select(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_input_select(hdspm); - hdspm_set_input_select(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -/* Simple Mixer - deprecated since to much faders ??? - MIXER interface says output (source, destination, value) - where source > MAX_channels are playback channels - on MADICARD - - playback mixer matrix: [channelout+64] [output] [value] - - input(thru) mixer matrix: [channelin] [output] [value] - (better do 2 kontrols for seperation ?) -*/ - -#define HDSPM_MIXER(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_mixer, \ - .get = snd_hdspm_get_mixer, \ - .put = snd_hdspm_put_mixer \ -} - -static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 3; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 65535; - uinfo->value.integer.step = 1; - return 0; -} - -static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int source; - int destination; - - source = ucontrol->value.integer.value[0]; - if (source < 0) - source = 0; - else if (source >= 2 * HDSPM_MAX_CHANNELS) - source = 2 * HDSPM_MAX_CHANNELS - 1; - - destination = ucontrol->value.integer.value[1]; - if (destination < 0) - destination = 0; - else if (destination >= HDSPM_MAX_CHANNELS) - destination = HDSPM_MAX_CHANNELS - 1; - - spin_lock_irq(&hdspm->lock); - if (source >= HDSPM_MAX_CHANNELS) - ucontrol->value.integer.value[2] = - hdspm_read_pb_gain(hdspm, destination, - source - HDSPM_MAX_CHANNELS); - else - ucontrol->value.integer.value[2] = - hdspm_read_in_gain(hdspm, destination, source); - - spin_unlock_irq(&hdspm->lock); - - return 0; -} - -static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int source; - int destination; - int gain; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - source = ucontrol->value.integer.value[0]; - destination = ucontrol->value.integer.value[1]; - - if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS) - return -1; - if (destination < 0 || destination >= HDSPM_MAX_CHANNELS) - return -1; - - gain = ucontrol->value.integer.value[2]; - - spin_lock_irq(&hdspm->lock); - - if (source >= HDSPM_MAX_CHANNELS) - change = gain != hdspm_read_pb_gain(hdspm, destination, - source - - HDSPM_MAX_CHANNELS); - else - change = - gain != hdspm_read_in_gain(hdspm, destination, source); - - if (change) { - if (source >= HDSPM_MAX_CHANNELS) - hdspm_write_pb_gain(hdspm, destination, - source - HDSPM_MAX_CHANNELS, - gain); - else - hdspm_write_in_gain(hdspm, destination, source, - gain); - } - spin_unlock_irq(&hdspm->lock); - - return change; -} - -/* The simple mixer control(s) provide gain control for the - basic 1:1 mappings of playback streams to output - streams. -*/ - -#define HDSPM_PLAYBACK_MIXER \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_playback_mixer, \ - .get = snd_hdspm_get_playback_mixer, \ - .put = snd_hdspm_put_playback_mixer \ -} - -static int snd_hdspm_info_playback_mixer(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 = 65536; - uinfo->value.integer.step = 1; - return 0; -} - -static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int channel; - int mapped_channel; - - channel = ucontrol->id.index - 1; - - snd_assert(channel >= 0 - || channel < HDSPM_MAX_CHANNELS, return -EINVAL); - - if ((mapped_channel = hdspm->channel_map[channel]) < 0) - return -EINVAL; - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = - hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); - spin_unlock_irq(&hdspm->lock); - - /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n", - ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]); - */ - - return 0; -} - -static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int channel; - int mapped_channel; - int gain; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - channel = ucontrol->id.index - 1; - - snd_assert(channel >= 0 - || channel < HDSPM_MAX_CHANNELS, return -EINVAL); - - if ((mapped_channel = hdspm->channel_map[channel]) < 0) - return -EINVAL; - - gain = ucontrol->value.integer.value[0]; - - spin_lock_irq(&hdspm->lock); - change = - gain != hdspm_read_pb_gain(hdspm, mapped_channel, - mapped_channel); - if (change) - hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel, - gain); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_WC_SYNC_CHECK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_sync_check, \ - .get = snd_hdspm_get_wc_sync_check \ -} - -static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol, - snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "No Lock", "Lock", "Sync" }; - 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 hdspm_wc_sync_check(hdspm_t * hdspm) -{ - int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - if (status2 & HDSPM_wcLock) { - if (status2 & HDSPM_wcSync) - return 2; - else - return 1; - } - return 0; -} - -static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm); - return 0; -} - - -#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_sync_check, \ - .get = snd_hdspm_get_madisync_sync_check \ -} - -static int hdspm_madisync_sync_check(hdspm_t * hdspm) -{ - int status = hdspm_read(hdspm, HDSPM_statusRegister); - if (status & HDSPM_madiLock) { - if (status & HDSPM_madiSync) - return 2; - else - return 1; - } - return 0; -} - -static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * - ucontrol) -{ - hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = - hdspm_madisync_sync_check(hdspm); - return 0; -} - - - - -static snd_kcontrol_new_t snd_hdspm_controls[] = { - - HDSPM_MIXER("Mixer", 0), -/* 'Sample Clock Source' complies with the alsa control naming scheme */ - HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), - - HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), - HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), - HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), - HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), -/* 'External Rate' complies with the alsa control naming scheme */ - HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), - HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), - HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0), - HDSPM_LINE_OUT("Line Out", 0), - HDSPM_TX_64("TX 64 channels mode", 0), - HDSPM_C_TMS("Clear Track Marker", 0), - HDSPM_SAFE_MODE("Safe Mode", 0), - HDSPM_INPUT_SELECT("Input Select", 0), -}; - -static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; - - -static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm) -{ - int i; - - for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) { - if (hdspm->system_sample_rate > 48000) { - hdspm->playback_mixer_ctls[i]->vd[0].access = - SNDRV_CTL_ELEM_ACCESS_INACTIVE | - SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE; - } else { - hdspm->playback_mixer_ctls[i]->vd[0].access = - SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_VOLATILE; - } - snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &hdspm->playback_mixer_ctls[i]->id); - } - - return 0; -} - - -static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm) -{ - unsigned int idx, limit; - int err; - snd_kcontrol_t *kctl; - - /* add control list first */ - - for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) { - if ((err = - snd_ctl_add(card, kctl = - snd_ctl_new1(&snd_hdspm_controls[idx], - hdspm))) < 0) { - return err; - } - } - - /* Channel playback mixer as default control - Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer - they are accesible via special IOCTL on hwdep - and the mixer 2dimensional mixer control */ - - snd_hdspm_playback_mixer.name = "Chn"; - limit = HDSPM_MAX_CHANNELS; - - /* The index values are one greater than the channel ID so that alsamixer - will display them correctly. We want to use the index for fast lookup - of the relevant channel, but if we use it at all, most ALSA software - does the wrong thing with it ... - */ - - for (idx = 0; idx < limit; ++idx) { - snd_hdspm_playback_mixer.index = idx + 1; - if ((err = snd_ctl_add(card, - kctl = - snd_ctl_new1 - (&snd_hdspm_playback_mixer, - hdspm)))) { - return err; - } - hdspm->playback_mixer_ctls[idx] = kctl; - } - - return 0; -} - -/*------------------------------------------------------------ - /proc interface - ------------------------------------------------------------*/ - -static void -snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer) -{ - hdspm_t *hdspm = (hdspm_t *) entry->private_data; - unsigned int status; - unsigned int status2; - char *pref_sync_ref; - char *autosync_ref; - char *system_clock_mode; - char *clock_source; - char *insel; - char *syncref; - int x, x2; - - status = hdspm_read(hdspm, HDSPM_statusRegister); - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - - snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", - hdspm->card_name, hdspm->card->number + 1, - hdspm->firmware_rev, - (status2 & HDSPM_version0) | - (status2 & HDSPM_version1) | (status2 & - HDSPM_version2)); - - snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", - hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); - - snd_iprintf(buffer, "--- System ---\n"); - - snd_iprintf(buffer, - "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", - status & HDSPM_audioIRQPending, - (status & HDSPM_midi0IRQPending) ? 1 : 0, - (status & HDSPM_midi1IRQPending) ? 1 : 0, - hdspm->irq_count); - snd_iprintf(buffer, - "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", - ((status & HDSPM_BufferID) ? 1 : 0), - (status & HDSPM_BufferPositionMask), - (status & HDSPM_BufferPositionMask) % (2 * - (int)hdspm-> - period_bytes), - ((status & HDSPM_BufferPositionMask) - - 64) % (2 * (int)hdspm->period_bytes), - (long) hdspm_hw_pointer(hdspm) * 4); - - snd_iprintf(buffer, - "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", - hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); - snd_iprintf(buffer, - "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n", - hdspm->control_register, hdspm->control2_register, - status, status2); - - snd_iprintf(buffer, "--- Settings ---\n"); - - x = 1 << (6 + - hdspm_decode_latency(hdspm-> - control_register & - HDSPM_LatencyMask)); - - snd_iprintf(buffer, - "Size (Latency): %d samples (2 periods of %lu bytes)\n", - x, (unsigned long) hdspm->period_bytes); - - snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", - (hdspm-> - control_register & HDSPM_LineOut) ? "on " : "off", - (hdspm->precise_ptr) ? "on" : "off"); - - switch (hdspm->control_register & HDSPM_InputMask) { - case HDSPM_InputOptical: - insel = "Optical"; - break; - case HDSPM_InputCoaxial: - insel = "Coaxial"; - break; - default: - insel = "Unkown"; - } - - switch (hdspm->control_register & HDSPM_SyncRefMask) { - case HDSPM_SyncRef_Word: - syncref = "WordClock"; - break; - case HDSPM_SyncRef_MADI: - syncref = "MADI"; - break; - default: - syncref = "Unkown"; - } - snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel, - syncref); - - snd_iprintf(buffer, - "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n", - (hdspm-> - control_register & HDSPM_clr_tms) ? "on" : "off", - (hdspm-> - control_register & HDSPM_TX_64ch) ? "64" : "56", - (hdspm-> - control_register & HDSPM_AutoInp) ? "on" : "off"); - - switch (hdspm_clock_source(hdspm)) { - case HDSPM_CLOCK_SOURCE_AUTOSYNC: - clock_source = "AutoSync"; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: - clock_source = "Internal 32 kHz"; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: - clock_source = "Internal 44.1 kHz"; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: - clock_source = "Internal 48 kHz"; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: - clock_source = "Internal 64 kHz"; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: - clock_source = "Internal 88.2 kHz"; - break; - case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: - clock_source = "Internal 96 kHz"; - break; - default: - clock_source = "Error"; - } - snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); - if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { - system_clock_mode = "Slave"; - } else { - system_clock_mode = "Master"; - } - snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); - - switch (hdspm_pref_sync_ref(hdspm)) { - case HDSPM_SYNC_FROM_WORD: - pref_sync_ref = "Word Clock"; - break; - case HDSPM_SYNC_FROM_MADI: - pref_sync_ref = "MADI Sync"; - break; - default: - pref_sync_ref = "XXXX Clock"; - break; - } - snd_iprintf(buffer, "Preferred Sync Reference: %s\n", - pref_sync_ref); - - snd_iprintf(buffer, "System Clock Frequency: %d\n", - hdspm->system_sample_rate); - - - snd_iprintf(buffer, "--- Status:\n"); - - x = status & HDSPM_madiSync; - x2 = status2 & HDSPM_wcSync; - - snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", - (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : - "NoLock", - (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : - "NoLock"); - - switch (hdspm_autosync_ref(hdspm)) { - case HDSPM_AUTOSYNC_FROM_WORD: - autosync_ref = "Word Clock"; - break; - case HDSPM_AUTOSYNC_FROM_MADI: - autosync_ref = "MADI Sync"; - break; - case HDSPM_AUTOSYNC_FROM_NONE: - autosync_ref = "Input not valid"; - break; - default: - autosync_ref = "---"; - break; - } - snd_iprintf(buffer, - "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", - autosync_ref, hdspm_external_sample_rate(hdspm), - (status & HDSPM_madiFreqMask) >> 22, - (status2 & HDSPM_wcFreqMask) >> 5); - - snd_iprintf(buffer, "Input: %s, Mode=%s\n", - (status & HDSPM_AB_int) ? "Coax" : "Optical", - (status & HDSPM_RX_64ch) ? "64 channels" : - "56 channels"); - - snd_iprintf(buffer, "\n"); -} - -static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm) -{ - snd_info_entry_t *entry; - - if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) - snd_info_set_text_ops(entry, hdspm, 1024, - snd_hdspm_proc_read); -} - -/*------------------------------------------------------------ - hdspm intitialize - ------------------------------------------------------------*/ - -static int snd_hdspm_set_defaults(hdspm_t * hdspm) -{ - unsigned int i; - - /* ASSUMPTION: hdspm->lock is either held, or there is no need to - hold it (e.g. during module initalization). - */ - - /* set defaults: */ - - hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ - hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ - HDSPM_InputCoaxial | /* Input Coax not Optical */ - HDSPM_SyncRef_MADI | /* Madi is syncclock */ - HDSPM_LineOut | /* Analog output in */ - HDSPM_TX_64ch | /* transmit in 64ch mode */ - HDSPM_AutoInp; /* AutoInput chossing (takeover) */ - - /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ - /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ - /* ! HDSPM_clr_tms = do not clear bits in track marks */ - - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - -#ifdef SNDRV_BIG_ENDIAN - hdspm->control2_register = HDSPM_BIGENDIAN_MODE; -#else - hdspm->control2_register = 0; -#endif - - hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register); - hdspm_compute_period_size(hdspm); - - /* silence everything */ - - all_in_all_mixer(hdspm, 0 * UNITY_GAIN); - - if (line_outs_monitor[hdspm->dev]) { - - snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n"); - - for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { - if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) - return -EIO; - } - } - - /* set a default rate so that the channel map is set up. */ - hdspm->channel_map = channel_map_madi_ss; - hdspm_set_rate(hdspm, 44100, 1); - - return 0; -} - - -/*------------------------------------------------------------ - interupt - ------------------------------------------------------------*/ - -static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id, - struct pt_regs *regs) -{ - hdspm_t *hdspm = (hdspm_t *) dev_id; - unsigned int status; - int audio; - int midi0; - int midi1; - unsigned int midi0status; - unsigned int midi1status; - int schedule = 0; - - status = hdspm_read(hdspm, HDSPM_statusRegister); - - audio = status & HDSPM_audioIRQPending; - midi0 = status & HDSPM_midi0IRQPending; - midi1 = status & HDSPM_midi1IRQPending; - - if (!audio && !midi0 && !midi1) - return IRQ_NONE; - - hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); - hdspm->irq_count++; - - midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff; - midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff; - - if (audio) { - - if (hdspm->capture_substream) - snd_pcm_period_elapsed(hdspm->pcm-> - streams - [SNDRV_PCM_STREAM_CAPTURE]. - substream); - - if (hdspm->playback_substream) - snd_pcm_period_elapsed(hdspm->pcm-> - streams - [SNDRV_PCM_STREAM_PLAYBACK]. - substream); - } - - if (midi0 && midi0status) { - /* we disable interrupts for this input until processing is done */ - hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - hdspm->midi[0].pending = 1; - schedule = 1; - } - if (midi1 && midi1status) { - /* we disable interrupts for this input until processing is done */ - hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - hdspm->midi[1].pending = 1; - schedule = 1; - } - if (schedule) - tasklet_hi_schedule(&hdspm->midi_tasklet); - return IRQ_HANDLED; -} - -/*------------------------------------------------------------ - pcm interface - ------------------------------------------------------------*/ - - -static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t * - substream) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - return hdspm_hw_pointer(hdspm); -} - -static char *hdspm_channel_buffer_location(hdspm_t * hdspm, - int stream, int channel) -{ - int mapped_channel; - - snd_assert(channel >= 0 - || channel < HDSPM_MAX_CHANNELS, return NULL); - - if ((mapped_channel = hdspm->channel_map[channel]) < 0) - return NULL; - - if (stream == SNDRV_PCM_STREAM_CAPTURE) { - return hdspm->capture_buffer + - mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; - } else { - return hdspm->playback_buffer + - mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; - } -} - - -/* dont know why need it ??? */ -static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream, - int channel, snd_pcm_uframes_t pos, - void __user *src, snd_pcm_uframes_t count) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - char *channel_buf; - - snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, - return -EINVAL); - - channel_buf = hdspm_channel_buffer_location(hdspm, - substream->pstr-> - stream, channel); - - snd_assert(channel_buf != NULL, return -EIO); - - return copy_from_user(channel_buf + pos * 4, src, count * 4); -} - -static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream, - int channel, snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - char *channel_buf; - - snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, - return -EINVAL); - - channel_buf = hdspm_channel_buffer_location(hdspm, - substream->pstr-> - stream, channel); - snd_assert(channel_buf != NULL, return -EIO); - return copy_to_user(dst, channel_buf + pos * 4, count * 4); -} - -static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = - hdspm_channel_buffer_location(hdspm, substream->pstr->stream, - channel); - snd_assert(channel_buf != NULL, return -EIO); - memset(channel_buf + pos * 4, 0, count * 4); - return 0; -} - -static int snd_hdspm_reset(snd_pcm_substream_t * substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - snd_pcm_substream_t *other; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = hdspm->capture_substream; - else - other = hdspm->playback_substream; - - if (hdspm->running) - runtime->status->hw_ptr = hdspm_hw_pointer(hdspm); - else - runtime->status->hw_ptr = 0; - if (other) { - struct list_head *pos; - snd_pcm_substream_t *s; - snd_pcm_runtime_t *oruntime = other->runtime; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); - if (s == other) { - oruntime->status->hw_ptr = - runtime->status->hw_ptr; - break; - } - } - } - return 0; -} - -static int snd_hdspm_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * params) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - int err; - int i; - pid_t this_pid; - pid_t other_pid; - struct snd_sg_buf *sgbuf; - - - spin_lock_irq(&hdspm->lock); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - this_pid = hdspm->playback_pid; - other_pid = hdspm->capture_pid; - } else { - this_pid = hdspm->capture_pid; - other_pid = hdspm->playback_pid; - } - - if ((other_pid > 0) && (this_pid != other_pid)) { - - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ - - if (params_rate(params) != hdspm->system_sample_rate) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; - } - - if (params_period_size(params) != hdspm->period_bytes / 4) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return -EBUSY; - } - - } - /* We're fine. */ - spin_unlock_irq(&hdspm->lock); - - /* how to make sure that the rate matches an externally-set one ? */ - - spin_lock_irq(&hdspm->lock); - if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_RATE); - return err; - } - spin_unlock_irq(&hdspm->lock); - - if ((err = - hdspm_set_interrupt_interval(hdspm, - params_period_size(params))) < - 0) { - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return err; - } - - /* Memory allocation, takashi's method, dont know if we should spinlock */ - /* malloc all buffer even if not enabled to get sure */ - /* malloc only needed bytes */ - err = - snd_pcm_lib_malloc_pages(substream, - HDSPM_CHANNEL_BUFFER_BYTES * - params_channels(params)); - if (err < 0) - return err; - - sgbuf = snd_pcm_substream_sgbuf(substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - - hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut, - params_channels(params)); - - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_out(hdspm, i, 1); - - hdspm->playback_buffer = - (unsigned char *) substream->runtime->dma_area; - } else { - hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn, - params_channels(params)); - - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_in(hdspm, i, 1); - - hdspm->capture_buffer = - (unsigned char *) substream->runtime->dma_area; - } - return 0; -} - -static int snd_hdspm_hw_free(snd_pcm_substream_t * substream) -{ - int i; - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - - /* params_channels(params) should be enough, - but to get sure in case of error */ - for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) - snd_hdspm_enable_out(hdspm, i, 0); - - hdspm->playback_buffer = NULL; - } else { - for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) - snd_hdspm_enable_in(hdspm, i, 0); - - hdspm->capture_buffer = NULL; - - } - - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static int snd_hdspm_channel_info(snd_pcm_substream_t * substream, - snd_pcm_channel_info_t * info) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - int mapped_channel; - - snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); - - if ((mapped_channel = hdspm->channel_map[info->channel]) < 0) - return -EINVAL; - - info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; - info->first = 0; - info->step = 32; - return 0; -} - -static int snd_hdspm_ioctl(snd_pcm_substream_t * substream, - unsigned int cmd, void *arg) -{ - switch (cmd) { - case SNDRV_PCM_IOCTL1_RESET: - { - return snd_hdspm_reset(substream); - } - - case SNDRV_PCM_IOCTL1_CHANNEL_INFO: - { - snd_pcm_channel_info_t *info = arg; - return snd_hdspm_channel_info(substream, info); - } - default: - break; - } - - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - snd_pcm_substream_t *other; - int running; - - spin_lock(&hdspm->lock); - running = hdspm->running; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - running |= 1 << substream->stream; - break; - case SNDRV_PCM_TRIGGER_STOP: - running &= ~(1 << substream->stream); - break; - default: - snd_BUG(); - spin_unlock(&hdspm->lock); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = hdspm->capture_substream; - else - other = hdspm->playback_substream; - - if (other) { - struct list_head *pos; - snd_pcm_substream_t *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); - if (s == other) { - snd_pcm_trigger_done(s, substream); - if (cmd == SNDRV_PCM_TRIGGER_START) - running |= 1 << s->stream; - else - running &= ~(1 << s->stream); - goto _ok; - } - } - if (cmd == SNDRV_PCM_TRIGGER_START) { - if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) - && substream->stream == - SNDRV_PCM_STREAM_CAPTURE) - hdspm_silence_playback(hdspm); - } else { - if (running && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - hdspm_silence_playback(hdspm); - } - } else { - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - hdspm_silence_playback(hdspm); - } - _ok: - snd_pcm_trigger_done(substream, substream); - if (!hdspm->running && running) - hdspm_start_audio(hdspm); - else if (hdspm->running && !running) - hdspm_stop_audio(hdspm); - hdspm->running = running; - spin_unlock(&hdspm->lock); - - return 0; -} - -static int snd_hdspm_prepare(snd_pcm_substream_t * substream) -{ - return 0; -} - -static unsigned int period_sizes[] = - { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; - -static snd_pcm_hardware_t snd_hdspm_playback_subinfo = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = HDSPM_MAX_CHANNELS, - .buffer_bytes_max = - HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, - .period_bytes_min = (64 * 4), - .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0 -}; - -static snd_pcm_hardware_t snd_hdspm_capture_subinfo = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = HDSPM_MAX_CHANNELS, - .buffer_bytes_max = - HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, - .period_bytes_min = (64 * 4), - .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0 -}; - -static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = { - .count = ARRAY_SIZE(period_sizes), - .list = period_sizes, - .mask = 0 -}; - - -static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params, - snd_pcm_hw_rule_t * rule) -{ - hdspm_t *hdspm = rule->private; - snd_interval_t *c = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - snd_interval_t *r = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - if (r->min > 48000) { - snd_interval_t t = { - .min = 1, - .max = hdspm->ds_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->max < 64000) { - snd_interval_t t = { - .min = 1, - .max = hdspm->ss_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } - return 0; -} - -static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params, - snd_pcm_hw_rule_t * rule) -{ - hdspm_t *hdspm = rule->private; - snd_interval_t *c = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - snd_interval_t *r = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - if (c->min <= hdspm->ss_channels) { - snd_interval_t t = { - .min = 32000, - .max = 48000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max > hdspm->ss_channels) { - snd_interval_t t = { - .min = 64000, - .max = 96000, - .integer = 1, - }; - - return snd_interval_refine(r, &t); - } - return 0; -} - -static int snd_hdspm_playback_open(snd_pcm_substream_t * substream) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; - - snd_printdd("Open device substream %d\n", substream->stream); - - spin_lock_irq(&hdspm->lock); - - snd_pcm_set_sync(substream); - - runtime->hw = snd_hdspm_playback_subinfo; - - if (hdspm->capture_substream == NULL) - hdspm_stop_audio(hdspm); - - hdspm->playback_pid = current->pid; - hdspm->playback_substream = substream; - - spin_unlock_irq(&hdspm->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - &hw_constraints_period_sizes); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_channels_rate, hdspm, - SNDRV_PCM_HW_PARAM_RATE, -1); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdspm_hw_rule_rate_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - - return 0; -} - -static int snd_hdspm_playback_release(snd_pcm_substream_t * substream) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - - spin_lock_irq(&hdspm->lock); - - hdspm->playback_pid = -1; - hdspm->playback_substream = NULL; - - spin_unlock_irq(&hdspm->lock); - - return 0; -} - - -static int snd_hdspm_capture_open(snd_pcm_substream_t * substream) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; - - spin_lock_irq(&hdspm->lock); - snd_pcm_set_sync(substream); - runtime->hw = snd_hdspm_capture_subinfo; - - if (hdspm->playback_substream == NULL) - hdspm_stop_audio(hdspm); - - hdspm->capture_pid = current->pid; - hdspm->capture_substream = substream; - - spin_unlock_irq(&hdspm->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - &hw_constraints_period_sizes); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_channels_rate, hdspm, - SNDRV_PCM_HW_PARAM_RATE, -1); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdspm_hw_rule_rate_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - return 0; -} - -static int snd_hdspm_capture_release(snd_pcm_substream_t * substream) -{ - hdspm_t *hdspm = snd_pcm_substream_chip(substream); - - spin_lock_irq(&hdspm->lock); - - hdspm->capture_pid = -1; - hdspm->capture_substream = NULL; - - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file) -{ - /* we have nothing to initialize but the call is required */ - return 0; -} - - -static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - hdspm_t *hdspm = (hdspm_t *) hw->private_data; - struct sndrv_hdspm_mixer_ioctl mixer; - hdspm_config_info_t info; - hdspm_version_t hdspm_version; - struct sndrv_hdspm_peak_rms_ioctl rms; - - switch (cmd) { - - - case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: - if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) - return -EFAULT; - /* maybe there is a chance to memorymap in future so dont touch just copy */ - if(copy_to_user_fromio((void __user *)rms.peak, - hdspm->iobase+HDSPM_MADI_peakrmsbase, - sizeof(hdspm_peak_rms_t)) != 0 ) - return -EFAULT; - - break; - - - case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: - - spin_lock_irq(&hdspm->lock); - info.pref_sync_ref = - (unsigned char) hdspm_pref_sync_ref(hdspm); - info.wordclock_sync_check = - (unsigned char) hdspm_wc_sync_check(hdspm); - - info.system_sample_rate = hdspm->system_sample_rate; - info.autosync_sample_rate = - hdspm_external_sample_rate(hdspm); - info.system_clock_mode = - (unsigned char) hdspm_system_clock_mode(hdspm); - info.clock_source = - (unsigned char) hdspm_clock_source(hdspm); - info.autosync_ref = - (unsigned char) hdspm_autosync_ref(hdspm); - info.line_out = (unsigned char) hdspm_line_out(hdspm); - info.passthru = 0; - spin_unlock_irq(&hdspm->lock); - if (copy_to_user((void __user *) arg, &info, sizeof(info))) - return -EFAULT; - break; - - case SNDRV_HDSPM_IOCTL_GET_VERSION: - hdspm_version.firmware_rev = hdspm->firmware_rev; - if (copy_to_user((void __user *) arg, &hdspm_version, - sizeof(hdspm_version))) - return -EFAULT; - break; - - case SNDRV_HDSPM_IOCTL_GET_MIXER: - if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) - return -EFAULT; - if (copy_to_user - ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t))) - return -EFAULT; - break; - - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_ops_t snd_hdspm_playback_ops = { - .open = snd_hdspm_playback_open, - .close = snd_hdspm_playback_release, - .ioctl = snd_hdspm_ioctl, - .hw_params = snd_hdspm_hw_params, - .hw_free = snd_hdspm_hw_free, - .prepare = snd_hdspm_prepare, - .trigger = snd_hdspm_trigger, - .pointer = snd_hdspm_hw_pointer, - .copy = snd_hdspm_playback_copy, - .silence = snd_hdspm_hw_silence, - .page = snd_pcm_sgbuf_ops_page, -}; - -static snd_pcm_ops_t snd_hdspm_capture_ops = { - .open = snd_hdspm_capture_open, - .close = snd_hdspm_capture_release, - .ioctl = snd_hdspm_ioctl, - .hw_params = snd_hdspm_hw_params, - .hw_free = snd_hdspm_hw_free, - .prepare = snd_hdspm_prepare, - .trigger = snd_hdspm_trigger, - .pointer = snd_hdspm_hw_pointer, - .copy = snd_hdspm_capture_copy, - .page = snd_pcm_sgbuf_ops_page, -}; - -static int __devinit snd_hdspm_create_hwdep(snd_card_t * card, - hdspm_t * hdspm) -{ - snd_hwdep_t *hw; - int err; - - if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0) - return err; - - hdspm->hwdep = hw; - hw->private_data = hdspm; - strcpy(hw->name, "HDSPM hwdep interface"); - - hw->ops.open = snd_hdspm_hwdep_dummy_op; - hw->ops.ioctl = snd_hdspm_hwdep_ioctl; - hw->ops.release = snd_hdspm_hwdep_dummy_op; - - return 0; -} - - -/*------------------------------------------------------------ - memory interface - ------------------------------------------------------------*/ -static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm) -{ - int err; - snd_pcm_t *pcm; - size_t wanted; - - pcm = hdspm->pcm; - - wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */ - - if ((err = - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(hdspm->pci), - wanted, - wanted)) < 0) { - snd_printdd("Could not preallocate %d Bytes\n", wanted); - - return err; - } else - snd_printdd(" Preallocated %d Bytes\n", wanted); - - return 0; -} - -static int snd_hdspm_memory_free(hdspm_t * hdspm) -{ - snd_printdd("memory_free_for_all %p\n", hdspm->pcm); - - snd_pcm_lib_preallocate_free_for_all(hdspm->pcm); - return 0; -} - - -static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf, - unsigned int reg, int channels) -{ - int i; - for (i = 0; i < (channels * 16); i++) - hdspm_write(hdspm, reg + 4 * i, - snd_pcm_sgbuf_get_addr(sgbuf, - (size_t) 4096 * i)); -} - -/* ------------- ALSA Devices ---------------------------- */ -static int __devinit snd_hdspm_create_pcm(snd_card_t * card, - hdspm_t * hdspm) -{ - snd_pcm_t *pcm; - int err; - - if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0) - return err; - - hdspm->pcm = pcm; - pcm->private_data = hdspm; - strcpy(pcm->name, hdspm->card_name); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_hdspm_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_hdspm_capture_ops); - - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - - if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0) - return err; - - return 0; -} - -static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm) -{ - snd_hdspm_flush_midi_input(hdspm, 0); - snd_hdspm_flush_midi_input(hdspm, 1); -} - -static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card, - hdspm_t * hdspm) -{ - int err; - - snd_printdd("Create card...\n"); - if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0) - return err; - - if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0) - return err; - - if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0) - return err; - - if ((err = snd_hdspm_create_controls(card, hdspm)) < 0) - return err; - - if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0) - return err; - - snd_printdd("proc init...\n"); - snd_hdspm_proc_init(hdspm); - - hdspm->system_sample_rate = -1; - hdspm->last_external_sample_rate = -1; - hdspm->last_internal_sample_rate = -1; - hdspm->playback_pid = -1; - hdspm->capture_pid = -1; - hdspm->capture_substream = NULL; - hdspm->playback_substream = NULL; - - snd_printdd("Set defaults...\n"); - if ((err = snd_hdspm_set_defaults(hdspm)) < 0) - return err; - - snd_printdd("Update mixer controls...\n"); - hdspm_update_simple_mixer_controls(hdspm); - - snd_printdd("Initializeing complete ???\n"); - - if ((err = snd_card_register(card)) < 0) { - snd_printk(KERN_ERR "HDSPM: error registering card\n"); - return err; - } - - snd_printdd("... yes now\n"); - - return 0; -} - -static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm, - int precise_ptr, int enable_monitor) -{ - struct pci_dev *pci = hdspm->pci; - int err; - int i; - - unsigned long io_extent; - - hdspm->irq = -1; - hdspm->irq_count = 0; - - hdspm->midi[0].rmidi = NULL; - hdspm->midi[1].rmidi = NULL; - hdspm->midi[0].input = NULL; - hdspm->midi[1].input = NULL; - hdspm->midi[0].output = NULL; - hdspm->midi[1].output = NULL; - spin_lock_init(&hdspm->midi[0].lock); - spin_lock_init(&hdspm->midi[1].lock); - hdspm->iobase = NULL; - hdspm->control_register = 0; - hdspm->control2_register = 0; - - hdspm->playback_buffer = NULL; - hdspm->capture_buffer = NULL; - - for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) - hdspm->playback_mixer_ctls[i] = NULL; - hdspm->mixer = NULL; - - hdspm->card = card; - - spin_lock_init(&hdspm->lock); - - tasklet_init(&hdspm->midi_tasklet, - hdspm_midi_tasklet, (unsigned long) hdspm); - - pci_read_config_word(hdspm->pci, - PCI_CLASS_REVISION, &hdspm->firmware_rev); - - strcpy(card->driver, "HDSPM"); - strcpy(card->mixername, "Xilinx FPGA"); - hdspm->card_name = "RME HDSPM MADI"; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - pci_set_master(hdspm->pci); - - if ((err = pci_request_regions(pci, "hdspm")) < 0) - return err; - - hdspm->port = pci_resource_start(pci, 0); - io_extent = pci_resource_len(pci, 0); - - snd_printdd("grabbed memory region 0x%lx-0x%lx\n", - hdspm->port, hdspm->port + io_extent - 1); - - - if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) { - snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n", - hdspm->port, hdspm->port + io_extent - 1); - return -EBUSY; - } - snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", - (unsigned long)hdspm->iobase, hdspm->port, - hdspm->port + io_extent - 1); - - if (request_irq(pci->irq, snd_hdspm_interrupt, - SA_INTERRUPT | SA_SHIRQ, "hdspm", - (void *) hdspm)) { - snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); - return -EBUSY; - } - - snd_printdd("use IRQ %d\n", pci->irq); - - hdspm->irq = pci->irq; - hdspm->precise_ptr = precise_ptr; - - hdspm->monitor_outs = enable_monitor; - - snd_printdd("kmalloc Mixer memory of %d Bytes\n", - sizeof(hdspm_mixer_t)); - if ((hdspm->mixer = - (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL)) - == NULL) { - snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n", - (int)sizeof(hdspm_mixer_t)); - return err; - } - - hdspm->ss_channels = MADI_SS_CHANNELS; - hdspm->ds_channels = MADI_DS_CHANNELS; - hdspm->qs_channels = MADI_QS_CHANNELS; - - snd_printdd("create alsa devices.\n"); - if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0) - return err; - - snd_hdspm_initialize_midi_flush(hdspm); - - return 0; -} - -static int snd_hdspm_free(hdspm_t * hdspm) -{ - - if (hdspm->port) { - - /* stop th audio, and cancel all interrupts */ - hdspm->control_register &= - ~(HDSPM_Start | HDSPM_AudioInterruptEnable - | HDSPM_Midi0InterruptEnable | - HDSPM_Midi1InterruptEnable); - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - } - - if (hdspm->irq >= 0) - free_irq(hdspm->irq, (void *) hdspm); - - - if (hdspm->mixer) - kfree(hdspm->mixer); - - if (hdspm->iobase) - iounmap(hdspm->iobase); - - snd_hdspm_memory_free(hdspm); - - if (hdspm->port) - pci_release_regions(hdspm->pci); - - pci_disable_device(hdspm->pci); - return 0; -} - -static void snd_hdspm_card_free(snd_card_t * card) -{ - hdspm_t *hdspm = (hdspm_t *) card->private_data; - - if (hdspm) - snd_hdspm_free(hdspm); -} - -static int __devinit snd_hdspm_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - hdspm_t *hdspm; - snd_card_t *card; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - if (!(card = snd_card_new(index[dev], id[dev], - THIS_MODULE, sizeof(hdspm_t)))) - return -ENOMEM; - - hdspm = (hdspm_t *) card->private_data; - card->private_free = snd_hdspm_card_free; - hdspm->dev = dev; - hdspm->pci = pci; - - if ((err = - snd_hdspm_create(card, hdspm, precise_ptr[dev], - enable_monitor[dev])) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->shortname, "HDSPM MADI"); - sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, - hdspm->port, hdspm->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - - dev++; - return 0; -} - -static void __devexit snd_hdspm_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = "RME Hammerfall DSP MADI", - .id_table = snd_hdspm_ids, - .probe = snd_hdspm_probe, - .remove = __devexit_p(snd_hdspm_remove), -}; - - -static int __init alsa_card_hdspm_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_hdspm_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_hdspm_init) -module_exit(alsa_card_hdspm_exit) diff --git a/trunk/sound/pci/rme9652/rme9652.c b/trunk/sound/pci/rme9652/rme9652.c index f3037402d58f..69cd81eaa111 100644 --- a/trunk/sound/pci/rme9652/rme9652.c +++ b/trunk/sound/pci/rme9652/rme9652.c @@ -303,22 +303,18 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer { dmab->dev.type = SNDRV_DMA_TYPE_DEV; dmab->dev.dev = snd_dma_pci_data(pci); - if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { - if (dmab->bytes >= size) - return 0; + if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), + size, dmab) < 0) + return -ENOMEM; } - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, dmab) < 0) - return -ENOMEM; return 0; } static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) { - if (dmab->area) { - dmab->dev.dev = NULL; /* make it anonymous */ + if (dmab->area) snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); - } } @@ -2668,7 +2664,7 @@ static struct pci_driver driver = { static int __init alsa_card_hammerfall_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_hammerfall_exit(void) diff --git a/trunk/sound/pci/sonicvibes.c b/trunk/sound/pci/sonicvibes.c index 60ecb2bdb65e..cfd2c5fd6ddf 100644 --- a/trunk/sound/pci/sonicvibes.c +++ b/trunk/sound/pci/sonicvibes.c @@ -1522,7 +1522,7 @@ static struct pci_driver driver = { static int __init alsa_card_sonicvibes_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_sonicvibes_exit(void) diff --git a/trunk/sound/pci/trident/trident.c b/trunk/sound/pci/trident/trident.c index 940d531575c0..ad58e08d66e2 100644 --- a/trunk/sound/pci/trident/trident.c +++ b/trunk/sound/pci/trident/trident.c @@ -143,8 +143,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, return err; } } - if (trident->device != TRIDENT_DEVICE_ID_SI7018 && - (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, + if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, trident->midi_port, 1, trident->irq, 0, &trident->rmidi)) < 0) { snd_card_free(card); @@ -185,7 +184,7 @@ static struct pci_driver driver = { static int __init alsa_card_trident_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_trident_exit(void) diff --git a/trunk/sound/pci/via82xx.c b/trunk/sound/pci/via82xx.c index 42c48f0ce8e8..9b4d74d49f98 100644 --- a/trunk/sound/pci/via82xx.c +++ b/trunk/sound/pci/via82xx.c @@ -101,7 +101,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); module_param_array(ac97_quirk, charp, NULL, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param_array(dxs_support, int, NULL, 0444); -MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); +MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)"); /* pci ids */ @@ -302,7 +302,6 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60); #define VIA_DXS_DISABLE 2 #define VIA_DXS_48K 3 #define VIA_DXS_NO_VRA 4 -#define VIA_DXS_SRC 5 /* @@ -381,7 +380,6 @@ struct _snd_via82xx { struct via_rate_lock rates[2]; /* playback and capture */ unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */ unsigned int no_vra: 1; /* no need to set VRA on DXS channels */ - unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */ unsigned int spdif_on: 1; /* only spdif rates work to external DACs */ snd_pcm_t *pcms[2]; @@ -491,8 +489,10 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream, snd_dma_free_pages(&dev->table); dev->table.area = NULL; } - kfree(dev->idx_table); - dev->idx_table = NULL; + if (dev->idx_table) { + kfree(dev->idx_table); + dev->idx_table = NULL; + } return 0; } @@ -924,17 +924,15 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) via82xx_t *chip = snd_pcm_substream_chip(substream); viadev_t *viadev = (viadev_t *)substream->runtime->private_data; snd_pcm_runtime_t *runtime = substream->runtime; - int ac97_rate = chip->dxs_src ? 48000 : runtime->rate; int rate_changed; u32 rbits; - if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0) + if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0) return rate_changed; if (rate_changed) { snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, chip->no_vra ? 48000 : runtime->rate); - snd_ac97_set_rate(chip->ac97, AC97_SPDIF, - chip->no_vra ? 48000 : runtime->rate); + snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); } if (runtime->rate == 48000) rbits = 0xfffff; @@ -1076,12 +1074,6 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst /* fixed DXS playback rate */ runtime->hw.rates = SNDRV_PCM_RATE_48000; runtime->hw.rate_min = runtime->hw.rate_max = 48000; - } else if (chip->dxs_src && viadev->reg_offset < 0x40) { - /* use full SRC capabilities of DXS */ - runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000); - runtime->hw.rate_min = 8000; - runtime->hw.rate_max = 48000; } else if (! ratep->rate) { int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; runtime->hw.rates = chip->ac97->rates[idx]; @@ -1558,51 +1550,51 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97) static struct ac97_quirk ac97_quirks[] = { { - .subvendor = 0x1106, - .subdevice = 0x4161, + .vendor = 0x1106, + .device = 0x4161, .codec_id = 0x56494161, /* VT1612A */ .name = "Soltek SL-75DRV5", .type = AC97_TUNE_NONE }, { /* FIXME: which codec? */ - .subvendor = 0x1106, - .subdevice = 0x4161, + .vendor = 0x1106, + .device = 0x4161, .name = "ASRock K7VT2", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1019, - .subdevice = 0x0a81, + .vendor = 0x1019, + .device = 0x0a81, .name = "ECS K7VTA3", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1019, - .subdevice = 0x0a85, + .vendor = 0x1019, + .device = 0x0a85, .name = "ECS L7VMM2", .type = AC97_TUNE_HP_ONLY }, { - .subvendor = 0x1849, - .subdevice = 0x3059, + .vendor = 0x1849, + .device = 0x3059, .name = "ASRock K7VM2", .type = AC97_TUNE_HP_ONLY /* VT1616 */ }, { - .subvendor = 0x14cd, - .subdevice = 0x7002, + .vendor = 0x14cd, + .device = 0x7002, .name = "Unknown", .type = AC97_TUNE_ALC_JACK }, { - .subvendor = 0x1071, - .subdevice = 0x8590, + .vendor = 0x1071, + .device = 0x8590, .name = "Mitac Mobo", .type = AC97_TUNE_ALC_JACK }, { - .subvendor = 0x161f, - .subdevice = 0x202b, + .vendor = 0x161f, + .device = 0x202b, .name = "Arima Notebook", .type = AC97_TUNE_HP_ONLY, }, @@ -2140,8 +2132,8 @@ static struct via823x_info via823x_cards[] __devinitdata = { * auto detection of DXS channel supports. */ struct dxs_whitelist { - unsigned short subvendor; - unsigned short subdevice; + unsigned short vendor; + unsigned short device; unsigned short mask; short action; /* new dxs_support value */ }; @@ -2149,44 +2141,38 @@ struct dxs_whitelist { static int __devinit check_dxs_list(struct pci_dev *pci) { static struct dxs_whitelist whitelist[] = { - { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */ - { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K }, - { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */ - { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */ - { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */ - { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ - { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ - { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ - { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */ - { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ - { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */ - { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ - { .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ - { .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */ - { .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ - { .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */ - { .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */ - { .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */ - { .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */ - { .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */ - { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ - { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ - { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ - { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ - { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */ - { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */ - { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ - { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ - { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ - { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */ - { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ - { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ - { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ - { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ - { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ - { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ - { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ - { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ + { .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */ + { .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K }, + { .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */ + { .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */ + { .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */ + { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ + { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ + { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ + { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ + { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ + { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ + { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */ + { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ + { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */ + { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */ + { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */ + { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ + { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ + { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ + { .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ + { .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */ + { .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */ + { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ + { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ + { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ + { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ + { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ + { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ + { .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ + { .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ + { .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ + { .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ { } /* terminator */ }; struct dxs_whitelist *w; @@ -2196,14 +2182,14 @@ static int __devinit check_dxs_list(struct pci_dev *pci) pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); - for (w = whitelist; w->subvendor; w++) { - if (w->subvendor != subsystem_vendor) + for (w = whitelist; w->vendor; w++) { + if (w->vendor != subsystem_vendor) continue; if (w->mask) { - if ((w->mask & subsystem_device) == w->subdevice) + if ((w->mask & subsystem_device) == w->device) return w->action; } else { - if (subsystem_device == w->subdevice) + if (subsystem_device == w->device) return w->action; } } @@ -2212,9 +2198,8 @@ static int __devinit check_dxs_list(struct pci_dev *pci) * not detected, try 48k rate only to be sure. */ printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n"); - printk(KERN_INFO " Please try dxs_support=5 option\n"); + printk(KERN_INFO " Please try dxs_support=1 or dxs_support=4 option\n"); printk(KERN_INFO " and report if it works on your machine.\n"); - printk(KERN_INFO " For more details, read ALSA-Configuration.txt.\n"); return VIA_DXS_48K; }; @@ -2303,10 +2288,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, chip->dxs_fixed = 1; else if (dxs_support[dev] == VIA_DXS_NO_VRA) chip->no_vra = 1; - else if (dxs_support[dev] == VIA_DXS_SRC) { - chip->no_vra = 1; - chip->dxs_src = 1; - } } if ((err = snd_via8233_init_misc(chip, dev)) < 0) goto __error; @@ -2353,7 +2334,7 @@ static struct pci_driver driver = { static int __init alsa_card_via82xx_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_via82xx_exit(void) diff --git a/trunk/sound/pci/via82xx_modem.c b/trunk/sound/pci/via82xx_modem.c index 5896d289f9ac..ea5c6f640159 100644 --- a/trunk/sound/pci/via82xx_modem.c +++ b/trunk/sound/pci/via82xx_modem.c @@ -352,8 +352,10 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream, snd_dma_free_pages(&dev->table); dev->table.area = NULL; } - kfree(dev->idx_table); - dev->idx_table = NULL; + if (dev->idx_table) { + kfree(dev->idx_table); + dev->idx_table = NULL; + } return 0; } @@ -418,10 +420,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97, { via82xx_t *chip = ac97->private_data; unsigned int xval; - if(reg == AC97_GPIO_STATUS) { - outl(val, VIAREG(chip, GPI_STATUS)); - return; - } + xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; xval |= reg << VIA_REG_AC97_CMD_SHIFT; @@ -545,6 +544,25 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd) return 0; } +static int snd_via82xx_modem_pcm_trigger(snd_pcm_substream_t * substream, int cmd) +{ + via82xx_t *chip = snd_pcm_substream_chip(substream); + unsigned int val = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS); + outl(val|AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS)); + break; + case SNDRV_PCM_TRIGGER_STOP: + val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS); + outl(val&~AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS)); + break; + default: + break; + } + return snd_via82xx_pcm_trigger(substream, cmd); +} + /* * pointer callbacks */ @@ -788,7 +806,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = { .hw_params = snd_via82xx_hw_params, .hw_free = snd_via82xx_hw_free, .prepare = snd_via82xx_pcm_prepare, - .trigger = snd_via82xx_pcm_trigger, + .trigger = snd_via82xx_modem_pcm_trigger, .pointer = snd_via686_pcm_pointer, .page = snd_pcm_sgbuf_ops_page, }; @@ -801,7 +819,7 @@ static snd_pcm_ops_t snd_via686_capture_ops = { .hw_params = snd_via82xx_hw_params, .hw_free = snd_via82xx_hw_free, .prepare = snd_via82xx_pcm_prepare, - .trigger = snd_via82xx_pcm_trigger, + .trigger = snd_via82xx_modem_pcm_trigger, .pointer = snd_via686_pcm_pointer, .page = snd_pcm_sgbuf_ops_page, }; @@ -920,7 +938,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip) * */ -static int snd_via82xx_chip_init(via82xx_t *chip) +static int __devinit snd_via82xx_chip_init(via82xx_t *chip) { unsigned int val; int max_count; @@ -1215,7 +1233,7 @@ static struct pci_driver driver = { static int __init alsa_card_via82xx_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_via82xx_exit(void) diff --git a/trunk/sound/pci/vx222/vx222.c b/trunk/sound/pci/vx222/vx222.c index dca6bd2c7580..4ffbb25658a5 100644 --- a/trunk/sound/pci/vx222/vx222.c +++ b/trunk/sound/pci/vx222/vx222.c @@ -260,7 +260,7 @@ static struct pci_driver driver = { static int __init alsa_card_vx222_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_vx222_exit(void) diff --git a/trunk/sound/pci/ymfpci/ymfpci.c b/trunk/sound/pci/ymfpci/ymfpci.c index 5b5b624b47d0..9f3ef22df08d 100644 --- a/trunk/sound/pci/ymfpci/ymfpci.c +++ b/trunk/sound/pci/ymfpci/ymfpci.c @@ -360,7 +360,7 @@ static struct pci_driver driver = { static int __init alsa_card_ymfpci_init(void) { - return pci_register_driver(&driver); + return pci_module_init(&driver); } static void __exit alsa_card_ymfpci_exit(void) diff --git a/trunk/sound/pci/ymfpci/ymfpci_main.c b/trunk/sound/pci/ymfpci/ymfpci_main.c index 2ae79610ecb5..05f1629760bc 100644 --- a/trunk/sound/pci/ymfpci/ymfpci_main.c +++ b/trunk/sound/pci/ymfpci/ymfpci_main.c @@ -829,7 +829,9 @@ static snd_pcm_hardware_t snd_ymfpci_capture = static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime) { - kfree(runtime->private_data); + ymfpci_pcm_t *ypcm = runtime->private_data; + + kfree(ypcm); } static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream) @@ -1419,15 +1421,17 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = { static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { + unsigned int mask = 1; + switch (kcontrol->private_value) { case YDSXGR_SPDIFOUTCTRL: break; case YDSXGR_SPDIFINCTRL: break; default: return -EINVAL; } - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; + uinfo->value.integer.max = mask; return 0; } @@ -1435,7 +1439,7 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t { ymfpci_t *chip = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value; - unsigned int shift = 0, mask = 1; + unsigned int shift = 0, mask = 1, invert = 0; switch (kcontrol->private_value) { case YDSXGR_SPDIFOUTCTRL: break; @@ -1443,6 +1447,8 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t default: return -EINVAL; } ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask; + if (invert) + ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; } @@ -1450,7 +1456,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t { ymfpci_t *chip = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value; - unsigned int shift = 0, mask = 1; + unsigned int shift = 0, mask = 1, invert = 0; int change; unsigned int val, oval; @@ -1460,6 +1466,8 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t default: return -EINVAL; } val = (ucontrol->value.integer.value[0] & mask); + if (invert) + val = mask - val; val <<= shift; spin_lock_irq(&chip->reg_lock); oval = snd_ymfpci_readl(chip, reg); @@ -1479,13 +1487,14 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { unsigned int reg = kcontrol->private_value; + unsigned int mask = 16383; if (reg < 0x80 || reg >= 0xc0) return -EINVAL; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; - uinfo->value.integer.max = 16383; + uinfo->value.integer.max = mask; return 0; } @@ -1493,7 +1502,7 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t { ymfpci_t *chip = snd_kcontrol_chip(kcontrol); unsigned int reg = kcontrol->private_value; - unsigned int shift_left = 0, shift_right = 16, mask = 16383; + unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0; unsigned int val; if (reg < 0x80 || reg >= 0xc0) @@ -1503,6 +1512,10 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t spin_unlock_irq(&chip->reg_lock); ucontrol->value.integer.value[0] = (val >> shift_left) & mask; ucontrol->value.integer.value[1] = (val >> shift_right) & mask; + if (invert) { + ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; + ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; + } return 0; } @@ -1510,7 +1523,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t { ymfpci_t *chip = snd_kcontrol_chip(kcontrol); unsigned int reg = kcontrol->private_value; - unsigned int shift_left = 0, shift_right = 16, mask = 16383; + unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0; int change; unsigned int val1, val2, oval; @@ -1518,6 +1531,10 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t return -EINVAL; val1 = ucontrol->value.integer.value[0] & mask; val2 = ucontrol->value.integer.value[1] & mask; + if (invert) { + val1 = mask - val1; + val2 = mask - val2; + } val1 <<= shift_left; val2 <<= shift_right; spin_lock_irq(&chip->reg_lock); diff --git a/trunk/sound/pcmcia/vx/vx_entry.c b/trunk/sound/pcmcia/vx/vx_entry.c index 332bbca3dfc4..53d8172c52ae 100644 --- a/trunk/sound/pcmcia/vx/vx_entry.c +++ b/trunk/sound/pcmcia/vx/vx_entry.c @@ -68,7 +68,8 @@ static int snd_vxpocket_free(vx_core_t *chip) if (hw) hw->card_list[vxp->index] = NULL; chip->card = NULL; - kfree(chip->dev); + if (chip->dev) + kfree(chip->dev); snd_vx_free_firmware(chip); kfree(chip); diff --git a/trunk/sound/synth/emux/emux_effect.c b/trunk/sound/synth/emux/emux_effect.c index 4764940f11a0..ec3fc1ba7fca 100644 --- a/trunk/sound/synth/emux/emux_effect.c +++ b/trunk/sound/synth/emux/emux_effect.c @@ -291,8 +291,10 @@ snd_emux_create_effect(snd_emux_port_t *p) void snd_emux_delete_effect(snd_emux_port_t *p) { - kfree(p->effect); - p->effect = NULL; + if (p->effect) { + kfree(p->effect); + p->effect = NULL; + } } void diff --git a/trunk/sound/usb/Kconfig b/trunk/sound/usb/Kconfig index f05d02f5b69f..9329e992c841 100644 --- a/trunk/sound/usb/Kconfig +++ b/trunk/sound/usb/Kconfig @@ -6,7 +6,6 @@ menu "USB devices" config SND_USB_AUDIO tristate "USB Audio/MIDI driver" depends on SND && USB - select SND_HWDEP select SND_RAWMIDI select SND_PCM help diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c index a75695045f29..aae66144d411 100644 --- a/trunk/sound/usb/usbaudio.c +++ b/trunk/sound/usb/usbaudio.c @@ -98,7 +98,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); #define MAX_PACKS 10 #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ #define MAX_URBS 5 /* max. 20ms long packets */ -#define SYNC_URBS 4 /* always four urbs for sync */ +#define SYNC_URBS 2 /* always two urbs for sync */ #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ typedef struct snd_usb_substream snd_usb_substream_t; @@ -177,7 +177,7 @@ struct snd_usb_substream { unsigned int nurbs; /* # urbs */ snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ - char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */ + char syncbuf[SYNC_URBS * MAX_PACKS * 4]; /* sync buffer; it's so small - let's get static */ char *tmpbuf; /* temporary buffer for playback */ u64 formats; /* format bitmasks (all or'ed) */ @@ -251,13 +251,17 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs, { unsigned char *cp = urb->transfer_buffer; snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; + int i, offs; + urb->number_of_packets = ctx->packets; urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 3; - urb->iso_frame_desc[0].offset = 0; - cp[0] = subs->freqn >> 2; - cp[1] = subs->freqn >> 10; - cp[2] = subs->freqn >> 18; + for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) { + urb->iso_frame_desc[i].length = 3; + urb->iso_frame_desc[i].offset = offs; + cp[0] = subs->freqn >> 2; + cp[1] = subs->freqn >> 10; + cp[2] = subs->freqn >> 18; + } return 0; } @@ -273,14 +277,18 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs, { unsigned char *cp = urb->transfer_buffer; snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; + int i, offs; + urb->number_of_packets = ctx->packets; urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 4; - urb->iso_frame_desc[0].offset = 0; - cp[0] = subs->freqn; - cp[1] = subs->freqn >> 8; - cp[2] = subs->freqn >> 16; - cp[3] = subs->freqn >> 24; + for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) { + urb->iso_frame_desc[i].length = 4; + urb->iso_frame_desc[i].offset = offs; + cp[0] = subs->freqn; + cp[1] = subs->freqn >> 8; + cp[2] = subs->freqn >> 16; + cp[3] = subs->freqn >> 24; + } return 0; } @@ -410,11 +418,15 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *urb) { + int i, offs; snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; + urb->number_of_packets = ctx->packets; urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 3; - urb->iso_frame_desc[0].offset = 0; + for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) { + urb->iso_frame_desc[i].length = 3; + urb->iso_frame_desc[i].offset = offs; + } return 0; } @@ -428,11 +440,15 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *urb) { + int i, offs; snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; + urb->number_of_packets = ctx->packets; urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 4; - urb->iso_frame_desc[0].offset = 0; + for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) { + urb->iso_frame_desc[i].length = 4; + urb->iso_frame_desc[i].offset = offs; + } return 0; } @@ -446,17 +462,31 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *urb) { - unsigned int f; + int i; + unsigned int f, found; + unsigned char *cp = urb->transfer_buffer; unsigned long flags; - if (urb->iso_frame_desc[0].status == 0 && - urb->iso_frame_desc[0].actual_length == 3) { - f = combine_triple((u8*)urb->transfer_buffer) << 2; - if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { - spin_lock_irqsave(&subs->lock, flags); - subs->freqm = f; - spin_unlock_irqrestore(&subs->lock, flags); + found = 0; + for (i = 0; i < urb->number_of_packets; i++, cp += 4) { + if (urb->iso_frame_desc[i].status || + urb->iso_frame_desc[i].actual_length < 3) + continue; + f = combine_triple(cp) << 2; +#if 0 + if (f < subs->freqn - (subs->freqn>>3) || f > subs->freqmax) { + snd_printd(KERN_WARNING "requested frequency %d (%u,%03uHz) out of range (current nominal %d (%u,%03uHz))\n", + f, f >> 14, (f & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1), + subs->freqn, subs->freqn >> 14, (subs->freqn & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1)); + continue; } +#endif + found = f; + } + if (found) { + spin_lock_irqsave(&subs->lock, flags); + subs->freqm = found; + spin_unlock_irqrestore(&subs->lock, flags); } return 0; @@ -472,17 +502,22 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *urb) { - unsigned int f; + int i; + unsigned int found; + unsigned char *cp = urb->transfer_buffer; unsigned long flags; - if (urb->iso_frame_desc[0].status == 0 && - urb->iso_frame_desc[0].actual_length == 4) { - f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff; - if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { - spin_lock_irqsave(&subs->lock, flags); - subs->freqm = f; - spin_unlock_irqrestore(&subs->lock, flags); - } + found = 0; + for (i = 0; i < urb->number_of_packets; i++, cp += 4) { + if (urb->iso_frame_desc[i].status || + urb->iso_frame_desc[i].actual_length < 4) + continue; + found = combine_quad(cp) & 0x0fffffff; + } + if (found) { + spin_lock_irqsave(&subs->lock, flags); + subs->freqm = found; + spin_unlock_irqrestore(&subs->lock, flags); } return 0; @@ -565,8 +600,6 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, /* set the buffer pointer */ urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; subs->hwptr += offs; - if (subs->hwptr == runtime->buffer_size) - subs->hwptr = 0; } spin_unlock_irqrestore(&subs->lock, flags); urb->transfer_buffer_length = offs * stride; @@ -859,8 +892,10 @@ static void release_urb_ctx(snd_urb_ctx_t *u) usb_free_urb(u->urb); u->urb = NULL; } - kfree(u->buf); - u->buf = NULL; + if (u->buf) { + kfree(u->buf); + u->buf = NULL; + } } /* @@ -878,8 +913,10 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force) release_urb_ctx(&subs->dataurb[i]); for (i = 0; i < SYNC_URBS; i++) release_urb_ctx(&subs->syncurb[i]); - kfree(subs->tmpbuf); - subs->tmpbuf = NULL; + if (subs->tmpbuf) { + kfree(subs->tmpbuf); + subs->tmpbuf = NULL; + } subs->nurbs = 0; } @@ -1002,19 +1039,22 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by snd_urb_ctx_t *u = &subs->syncurb[i]; u->index = i; u->subs = subs; - u->packets = 1; - u->urb = usb_alloc_urb(1, GFP_KERNEL); + u->packets = nrpacks; + u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); if (! u->urb) { release_substream_urbs(subs, 0); return -ENOMEM; } - u->urb->transfer_buffer = subs->syncbuf + i * 4; - u->urb->transfer_buffer_length = 4; + u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4; + u->urb->transfer_buffer_length = nrpacks * 4; u->urb->dev = subs->dev; u->urb->pipe = subs->syncpipe; u->urb->transfer_flags = URB_ISO_ASAP; - u->urb->number_of_packets = 1; - u->urb->interval = 1 << subs->syncinterval; + u->urb->number_of_packets = u->packets; + if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) + u->urb->interval = 8; + else + u->urb->interval = 1; u->urb->context = u; u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb); } @@ -1232,17 +1272,7 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt) subs->syncpipe = usb_rcvisocpipe(dev, ep); else subs->syncpipe = usb_sndisocpipe(dev, ep); - if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && - get_endpoint(alts, 1)->bRefresh >= 1 && - get_endpoint(alts, 1)->bRefresh <= 9) - subs->syncinterval = get_endpoint(alts, 1)->bRefresh; - else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) - subs->syncinterval = 1; - else if (get_endpoint(alts, 1)->bInterval >= 1 && - get_endpoint(alts, 1)->bInterval <= 16) - subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; - else - subs->syncinterval = 3; + subs->syncinterval = get_endpoint(alts, 1)->bRefresh; } /* always fill max packet size */ @@ -1960,11 +1990,10 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe snd_iprintf(buffer, "%d ", subs->dataurb[i].packets); snd_iprintf(buffer, "]\n"); snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); - snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", + snd_iprintf(buffer, " Momentary freq = %u Hz\n", snd_usb_get_speed(subs->dev) == USB_SPEED_FULL ? get_full_speed_hz(subs->freqm) - : get_high_speed_hz(subs->freqm), - subs->freqm >> 16, subs->freqm & 0xffff); + : get_high_speed_hz(subs->freqm)); } else { snd_iprintf(buffer, " Status: Stop\n"); } @@ -2154,15 +2183,17 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor /* * check if the device uses big-endian samples */ -static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp) +static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp) { - switch (chip->usb_id) { - case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ - if (fp->endpoint & USB_DIR_IN) + /* M-Audio */ + if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) { + /* Quattro: captured data only */ + if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 && + fp->endpoint & USB_DIR_IN) + return 1; + /* Audiophile USB */ + if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003) return 1; - break; - case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ - return 1; } return 0; } @@ -2176,7 +2207,7 @@ static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp) * @format: the format tag (wFormatTag) * @fmt: the format type descriptor */ -static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp, +static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp, int format, unsigned char *fmt) { int pcm_format; @@ -2189,12 +2220,12 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat * switch (format) { case 0: /* some devices don't define this correctly... */ snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", - chip->dev->devnum, fp->iface, fp->altsetting); + dev->devnum, fp->iface, fp->altsetting); /* fall-through */ case USB_AUDIO_FORMAT_PCM: if (sample_width > sample_bytes * 8) { snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, + dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes); } /* check the format byte size */ @@ -2203,13 +2234,13 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat * pcm_format = SNDRV_PCM_FORMAT_S8; break; case 2: - if (is_big_endian_format(chip, fp)) + if (is_big_endian_format(dev, fp)) pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ else pcm_format = SNDRV_PCM_FORMAT_S16_LE; break; case 3: - if (is_big_endian_format(chip, fp)) + if (is_big_endian_format(dev, fp)) pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ else pcm_format = SNDRV_PCM_FORMAT_S24_3LE; @@ -2219,14 +2250,14 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat * break; default: snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", - chip->dev->devnum, fp->iface, - fp->altsetting, sample_width, sample_bytes); + dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes); break; } break; case USB_AUDIO_FORMAT_PCM8: /* Dallas DS4201 workaround */ - if (chip->usb_id == USB_ID(0x04fa, 0x4201)) + if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa && + le16_to_cpu(dev->descriptor.idProduct) == 0x4201) pcm_format = SNDRV_PCM_FORMAT_S8; else pcm_format = SNDRV_PCM_FORMAT_U8; @@ -2242,7 +2273,7 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat * break; default: snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, format); + dev->devnum, fp->iface, fp->altsetting, format); break; } return pcm_format; @@ -2259,13 +2290,13 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat * * @offset: the start offset of descriptor pointing the rate type * (7 for type I and II, 8 for type II) */ -static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp, +static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp, unsigned char *fmt, int offset) { int nr_rates = fmt[offset]; if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", - chip->dev->devnum, fp->iface, fp->altsetting); + dev->devnum, fp->iface, fp->altsetting); return -1; } @@ -2312,7 +2343,7 @@ static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *f /* * parse the format type I and III descriptors */ -static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp, +static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, int format, unsigned char *fmt) { int pcm_format; @@ -2324,7 +2355,7 @@ static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp, */ pcm_format = SNDRV_PCM_FORMAT_S16_LE; } else { - pcm_format = parse_audio_format_i_type(chip, fp, format, fmt); + pcm_format = parse_audio_format_i_type(dev, fp, format, fmt); if (pcm_format < 0) return -1; } @@ -2332,16 +2363,16 @@ static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp, fp->channels = fmt[4]; if (fp->channels < 1) { snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); + dev->devnum, fp->iface, fp->altsetting, fp->channels); return -1; } - return parse_audio_format_rates(chip, fp, fmt, 7); + return parse_audio_format_rates(dev, fp, fmt, 7); } /* * prase the format type II descriptor */ -static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp, +static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, int format, unsigned char *fmt) { int brate, framesize; @@ -2356,7 +2387,7 @@ static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp, break; default: snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n", - chip->dev->devnum, fp->iface, fp->altsetting, format); + dev->devnum, fp->iface, fp->altsetting, format); fp->format = SNDRV_PCM_FORMAT_MPEG; break; } @@ -2365,10 +2396,10 @@ static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp, framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */ snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); fp->frame_size = framesize; - return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */ + return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */ } -static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp, +static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, int format, unsigned char *fmt, int stream) { int err; @@ -2376,30 +2407,29 @@ static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp, switch (fmt[3]) { case USB_FORMAT_TYPE_I: case USB_FORMAT_TYPE_III: - err = parse_audio_format_i(chip, fp, format, fmt); + err = parse_audio_format_i(dev, fp, format, fmt); break; case USB_FORMAT_TYPE_II: - err = parse_audio_format_ii(chip, fp, format, fmt); + err = parse_audio_format_ii(dev, fp, format, fmt); break; default: snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", - chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]); + dev->devnum, fp->iface, fp->altsetting, fmt[3]); return -1; } fp->fmt_type = fmt[3]; if (err < 0) return err; #if 1 - /* FIXME: temporary hack for extigy/audigy 2 nx */ + /* FIXME: temporary hack for extigy */ /* extigy apparently supports sample rates other than 48k * but not in ordinary way. so we enable only 48k atm. */ - if (chip->usb_id == USB_ID(0x041e, 0x3000) || - chip->usb_id == USB_ID(0x041e, 0x3020)) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && + le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { if (fmt[3] == USB_FORMAT_TYPE_I && stream == SNDRV_PCM_STREAM_PLAYBACK && - fp->rates != SNDRV_PCM_RATE_48000 && - fp->rates != SNDRV_PCM_RATE_96000) + fp->rates != SNDRV_PCM_RATE_48000) return -1; /* use 48k only */ } #endif @@ -2498,35 +2528,40 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) /* some quirks for attributes here */ - switch (chip->usb_id) { - case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ + /* workaround for AudioTrak Optoplay */ + if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 && + le16_to_cpu(dev->descriptor.idProduct) == 0x0053) { /* Optoplay sets the sample rate attribute although * it seems not supporting it in fact. */ fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE; - break; - case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ - case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ + } + + /* workaround for M-Audio Audiophile USB */ + if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 && + le16_to_cpu(dev->descriptor.idProduct) == 0x2003) { /* doesn't set the sample rate attribute, but supports it */ fp->attributes |= EP_CS_ATTR_SAMPLE_RATE; - break; - case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ - case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is - an older model 77d:223) */ + } + /* * plantronics headset and Griffin iMic have set adaptive-in * although it's really not... */ + if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f && + le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) || + /* Griffin iMic (note that there is an older model 77d:223) */ + (le16_to_cpu(dev->descriptor.idVendor) == 0x077d && + le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) { fp->ep_attr &= ~EP_ATTR_MASK; if (stream == SNDRV_PCM_STREAM_PLAYBACK) fp->ep_attr |= EP_ATTR_ADAPTIVE; else fp->ep_attr |= EP_ATTR_SYNC; - break; } /* ok, let's parse further... */ - if (parse_audio_format(chip, fp, format, fmt, stream) < 0) { + if (parse_audio_format(dev, fp, format, fmt, stream) < 0) { kfree(fp->rate_table); kfree(fp); continue; @@ -2552,7 +2587,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) * disconnect streams * called from snd_usb_audio_disconnect() */ -static void snd_usb_stream_disconnect(struct list_head *head) +static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver) { int idx; snd_usb_stream_t *as; @@ -2761,7 +2796,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &ua25_ep }; - if (chip->usb_id == USB_ID(0x0582, 0x002b)) + if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b) return snd_usb_create_midi_interface(chip, iface, &ua700_quirk); else @@ -2924,25 +2959,6 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac return 0; } -static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) -{ -#if 0 - /* TODO: enable this when high speed synchronization actually works */ - u8 buf = 1; - - snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, - 0, 0, &buf, 1, 1000); - if (buf == 0) { - snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - 1, 2000, NULL, 0, 1000); - return -ENODEV; - } -#endif - return 0; -} - /* * audio-interface quirks @@ -2999,8 +3015,8 @@ static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *bu snd_usb_audio_t *chip = entry->private_data; if (! chip->shutdown) snd_iprintf(buffer, "%04x:%04x\n", - USB_ID_VENDOR(chip->usb_id), - USB_ID_PRODUCT(chip->usb_id)); + le16_to_cpu(chip->dev->descriptor.idVendor), + le16_to_cpu(chip->dev->descriptor.idProduct)); } static void snd_usb_audio_create_proc(snd_usb_audio_t *chip) @@ -3070,11 +3086,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, chip->index = idx; chip->dev = dev; chip->card = card; - chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); INIT_LIST_HEAD(&chip->pcm_list); INIT_LIST_HEAD(&chip->midi_list); - INIT_LIST_HEAD(&chip->mixer_list); if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_usb_audio_free(chip); @@ -3084,7 +3097,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, strcpy(card->driver, "USB-Audio"); sprintf(component, "USB%04x:%04x", - USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id)); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); snd_component_add(card, component); /* retrieve the device string as shortname */ @@ -3096,8 +3110,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, card->shortname, sizeof(card->shortname)) <= 0) { /* no name available from anywhere, so use ID */ sprintf(card->shortname, "USB Device %#04x:%#04x", - USB_ID_VENDOR(chip->usb_id), - USB_ID_PRODUCT(chip->usb_id)); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); } } @@ -3128,6 +3142,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, snd_usb_audio_create_proc(chip); + snd_card_set_dev(card, &dev->dev); + *rchip = chip; return 0; } @@ -3153,28 +3169,21 @@ static void *snd_usb_audio_probe(struct usb_device *dev, snd_usb_audio_t *chip; struct usb_host_interface *alts; int ifnum; - u32 id; alts = &intf->altsetting[0]; ifnum = get_iface_desc(alts)->bInterfaceNumber; - id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) goto __err_val; /* SB Extigy needs special boot-up sequence */ /* if more models come, this will go to the quirk list. */ - if (id == USB_ID(0x041e, 0x3000)) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && + le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { if (snd_usb_extigy_boot_quirk(dev, intf) < 0) goto __err_val; config = dev->actconfig; } - /* SB Audigy 2 NX needs its own boot-up magic, too */ - if (id == USB_ID(0x041e, 0x3020)) { - if (snd_usb_audigy2nx_boot_quirk(dev) < 0) - goto __err_val; - } /* * found a config. now register to ALSA @@ -3204,12 +3213,11 @@ static void *snd_usb_audio_probe(struct usb_device *dev, } for (i = 0; i < SNDRV_CARDS; i++) if (enable[i] && ! usb_chip[i] && - (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && - (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { + (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) && + (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) { if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { goto __error; } - snd_card_set_dev(chip->card, &intf->dev); break; } if (! chip) { @@ -3273,15 +3281,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) snd_card_disconnect(card); /* release the pcm resources */ list_for_each(p, &chip->pcm_list) { - snd_usb_stream_disconnect(p); + snd_usb_stream_disconnect(p, &usb_audio_driver); } /* release the midi resources */ list_for_each(p, &chip->midi_list) { - snd_usbmidi_disconnect(p); - } - /* release mixer resources */ - list_for_each(p, &chip->mixer_list) { - snd_usb_mixer_disconnect(p); + snd_usbmidi_disconnect(p, &usb_audio_driver); } usb_chip[chip->index] = NULL; up(®ister_mutex); diff --git a/trunk/sound/usb/usbaudio.h b/trunk/sound/usb/usbaudio.h index aedb42aaa749..eecbf19fcb6f 100644 --- a/trunk/sound/usb/usbaudio.h +++ b/trunk/sound/usb/usbaudio.h @@ -118,11 +118,6 @@ /* maximum number of endpoints per interface */ #define MIDI_MAX_ENDPOINTS 2 -/* handling of USB vendor/product ID pairs as 32-bit numbers */ -#define USB_ID(vendor, product) (((vendor) << 16) | (product)) -#define USB_ID_VENDOR(id) ((id) >> 16) -#define USB_ID_PRODUCT(id) ((u16)(id)) - /* */ @@ -132,7 +127,6 @@ struct snd_usb_audio { int index; struct usb_device *dev; snd_card_t *card; - u32 usb_id; int shutdown; int num_interfaces; @@ -142,7 +136,7 @@ struct snd_usb_audio { struct list_head midi_list; /* list of midi interfaces */ int next_midi_device; - struct list_head mixer_list; /* list of mixer interfaces */ + unsigned int ignore_ctl_error; /* for mixer */ }; /* @@ -225,12 +219,11 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); -void snd_usb_mixer_disconnect(struct list_head *p); int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); void snd_usbmidi_input_stop(struct list_head* p); void snd_usbmidi_input_start(struct list_head* p); -void snd_usbmidi_disconnect(struct list_head *p); +void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver); /* * retrieve usb_interface descriptor from the host interface diff --git a/trunk/sound/usb/usbmidi.c b/trunk/sound/usb/usbmidi.c index bee70068dce0..5d32857ff955 100644 --- a/trunk/sound/usb/usbmidi.c +++ b/trunk/sound/usb/usbmidi.c @@ -912,7 +912,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi) /* * Unlinks all URBs (must be done before the usb_device is deleted). */ -void snd_usbmidi_disconnect(struct list_head* p) +void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver) { snd_usb_midi_t* umidi; int i; @@ -955,87 +955,88 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi * such as internal control or synthesizer ports. */ static struct { - u32 id; + __u16 vendor; + __u16 product; int port; const char *name_format; } snd_usbmidi_port_names[] = { /* Roland UA-100 */ - { USB_ID(0x0582, 0x0000), 2, "%s Control" }, + {0x0582, 0x0000, 2, "%s Control"}, /* Roland SC-8850 */ - { USB_ID(0x0582, 0x0003), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0003), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0003), 2, "%s Part C" }, - { USB_ID(0x0582, 0x0003), 3, "%s Part D" }, - { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" }, - { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" }, + {0x0582, 0x0003, 0, "%s Part A"}, + {0x0582, 0x0003, 1, "%s Part B"}, + {0x0582, 0x0003, 2, "%s Part C"}, + {0x0582, 0x0003, 3, "%s Part D"}, + {0x0582, 0x0003, 4, "%s MIDI 1"}, + {0x0582, 0x0003, 5, "%s MIDI 2"}, /* Roland U-8 */ - { USB_ID(0x0582, 0x0004), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0004), 1, "%s Control" }, + {0x0582, 0x0004, 0, "%s MIDI"}, + {0x0582, 0x0004, 1, "%s Control"}, /* Roland SC-8820 */ - { USB_ID(0x0582, 0x0007), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0007), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0007), 2, "%s MIDI" }, + {0x0582, 0x0007, 0, "%s Part A"}, + {0x0582, 0x0007, 1, "%s Part B"}, + {0x0582, 0x0007, 2, "%s MIDI"}, /* Roland SK-500 */ - { USB_ID(0x0582, 0x000b), 0, "%s Part A" }, - { USB_ID(0x0582, 0x000b), 1, "%s Part B" }, - { USB_ID(0x0582, 0x000b), 2, "%s MIDI" }, + {0x0582, 0x000b, 0, "%s Part A"}, + {0x0582, 0x000b, 1, "%s Part B"}, + {0x0582, 0x000b, 2, "%s MIDI"}, /* Roland SC-D70 */ - { USB_ID(0x0582, 0x000c), 0, "%s Part A" }, - { USB_ID(0x0582, 0x000c), 1, "%s Part B" }, - { USB_ID(0x0582, 0x000c), 2, "%s MIDI" }, + {0x0582, 0x000c, 0, "%s Part A"}, + {0x0582, 0x000c, 1, "%s Part B"}, + {0x0582, 0x000c, 2, "%s MIDI"}, /* Edirol UM-880 */ - { USB_ID(0x0582, 0x0014), 8, "%s Control" }, + {0x0582, 0x0014, 8, "%s Control"}, /* Edirol SD-90 */ - { USB_ID(0x0582, 0x0016), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0016), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" }, - { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" }, + {0x0582, 0x0016, 0, "%s Part A"}, + {0x0582, 0x0016, 1, "%s Part B"}, + {0x0582, 0x0016, 2, "%s MIDI 1"}, + {0x0582, 0x0016, 3, "%s MIDI 2"}, /* Edirol UM-550 */ - { USB_ID(0x0582, 0x0023), 5, "%s Control" }, + {0x0582, 0x0023, 5, "%s Control"}, /* Edirol SD-20 */ - { USB_ID(0x0582, 0x0027), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0027), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0027), 2, "%s MIDI" }, + {0x0582, 0x0027, 0, "%s Part A"}, + {0x0582, 0x0027, 1, "%s Part B"}, + {0x0582, 0x0027, 2, "%s MIDI"}, /* Edirol SD-80 */ - { USB_ID(0x0582, 0x0029), 0, "%s Part A" }, - { USB_ID(0x0582, 0x0029), 1, "%s Part B" }, - { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" }, - { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" }, + {0x0582, 0x0029, 0, "%s Part A"}, + {0x0582, 0x0029, 1, "%s Part B"}, + {0x0582, 0x0029, 2, "%s MIDI 1"}, + {0x0582, 0x0029, 3, "%s MIDI 2"}, /* Edirol UA-700 */ - { USB_ID(0x0582, 0x002b), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x002b), 1, "%s Control" }, + {0x0582, 0x002b, 0, "%s MIDI"}, + {0x0582, 0x002b, 1, "%s Control"}, /* Roland VariOS */ - { USB_ID(0x0582, 0x002f), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" }, - { USB_ID(0x0582, 0x002f), 2, "%s Sync" }, + {0x0582, 0x002f, 0, "%s MIDI"}, + {0x0582, 0x002f, 1, "%s External MIDI"}, + {0x0582, 0x002f, 2, "%s Sync"}, /* Edirol PCR */ - { USB_ID(0x0582, 0x0033), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0033), 1, "%s 1" }, - { USB_ID(0x0582, 0x0033), 2, "%s 2" }, + {0x0582, 0x0033, 0, "%s MIDI"}, + {0x0582, 0x0033, 1, "%s 1"}, + {0x0582, 0x0033, 2, "%s 2"}, /* BOSS GS-10 */ - { USB_ID(0x0582, 0x003b), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x003b), 1, "%s Control" }, + {0x0582, 0x003b, 0, "%s MIDI"}, + {0x0582, 0x003b, 1, "%s Control"}, /* Edirol UA-1000 */ - { USB_ID(0x0582, 0x0044), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0044), 1, "%s Control" }, + {0x0582, 0x0044, 0, "%s MIDI"}, + {0x0582, 0x0044, 1, "%s Control"}, /* Edirol UR-80 */ - { USB_ID(0x0582, 0x0048), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x0048), 1, "%s 1" }, - { USB_ID(0x0582, 0x0048), 2, "%s 2" }, + {0x0582, 0x0048, 0, "%s MIDI"}, + {0x0582, 0x0048, 1, "%s 1"}, + {0x0582, 0x0048, 2, "%s 2"}, /* Edirol PCR-A */ - { USB_ID(0x0582, 0x004d), 0, "%s MIDI" }, - { USB_ID(0x0582, 0x004d), 1, "%s 1" }, - { USB_ID(0x0582, 0x004d), 2, "%s 2" }, + {0x0582, 0x004d, 0, "%s MIDI"}, + {0x0582, 0x004d, 1, "%s 1"}, + {0x0582, 0x004d, 2, "%s 2"}, /* M-Audio MidiSport 8x8 */ - { USB_ID(0x0763, 0x1031), 8, "%s Control" }, - { USB_ID(0x0763, 0x1033), 8, "%s Control" }, + {0x0763, 0x1031, 8, "%s Control"}, + {0x0763, 0x1033, 8, "%s Control"}, /* MOTU Fastlane */ - { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" }, - { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" }, + {0x07fd, 0x0001, 0, "%s MIDI A"}, + {0x07fd, 0x0001, 1, "%s MIDI B"}, /* Emagic Unitor8/AMT8/MT4 */ - { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" }, - { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" }, - { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" }, + {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, @@ -1043,6 +1044,7 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, snd_rawmidi_substream_t** rsubstream) { int i; + __u16 vendor, product; const char *name_format; snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number); @@ -1053,8 +1055,11 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, /* TODO: read port name from jack descriptor */ name_format = "%s MIDI %d"; + vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor); + product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct); for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { - if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id && + if (snd_usbmidi_port_names[i].vendor == vendor && + snd_usbmidi_port_names[i].product == product && snd_usbmidi_port_names[i].port == number) { name_format = snd_usbmidi_port_names[i].name_format; break; @@ -1221,12 +1226,9 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi, struct usb_endpoint_descriptor* epd; int i, out_eps = 0, in_eps = 0; - if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582) + if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582) snd_usbmidi_switch_roland_altsetting(umidi); - if (endpoint[0].out_ep || endpoint[0].in_ep) - return 0; - intf = umidi->iface; if (!intf || intf->num_altsetting < 1) return -ENOENT; diff --git a/trunk/sound/usb/usbmixer.c b/trunk/sound/usb/usbmixer.c index e73c1c9d3e73..5f1906915aa6 100644 --- a/trunk/sound/usb/usbmixer.c +++ b/trunk/sound/usb/usbmixer.c @@ -35,11 +35,10 @@ #include #include #include -#include -#include #include "usbaudio.h" + /* */ @@ -51,31 +50,6 @@ typedef struct usb_audio_term usb_audio_term_t; typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; -struct usb_mixer_interface { - snd_usb_audio_t *chip; - unsigned int ctrlif; - struct list_head list; - unsigned int ignore_ctl_error; - struct urb *urb; - usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */ - - /* Sound Blaster remote control stuff */ - enum { - RC_NONE, - RC_EXTIGY, - RC_AUDIGY2NX, - } rc_type; - unsigned long rc_hwdep_open; - u32 rc_code; - wait_queue_head_t rc_waitq; - struct urb *rc_urb; - struct usb_ctrlrequest *rc_setup_packet; - u8 rc_buffer[6]; - - u8 audigy2nx_leds[3]; -}; - - struct usb_audio_term { int id; int type; @@ -88,26 +62,26 @@ struct usbmix_name_map; struct usb_mixer_build { snd_usb_audio_t *chip; - struct usb_mixer_interface *mixer; unsigned char *buffer; unsigned int buflen; - DECLARE_BITMAP(unitbitmap, 256); + unsigned int ctrlif; + unsigned short vendor; + unsigned short product; + DECLARE_BITMAP(unitbitmap, 32*32); usb_audio_term_t oterm; const struct usbmix_name_map *map; - const struct usbmix_selector_map *selector_map; }; struct usb_mixer_elem_info { - struct usb_mixer_interface *mixer; - usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */ - snd_ctl_elem_id_t *elem_id; + snd_usb_audio_t *chip; + unsigned int ctrlif; unsigned int id; unsigned int control; /* CS or ICN (high byte) */ unsigned int cmask; /* channel mask bitmap: 0 = master */ int channels; int val_type; int min, max, res; - u8 initialized; + unsigned int initialized: 1; }; @@ -213,21 +187,6 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control) return 0; } -/* get the mapped selector source name */ -static int check_mapped_selector_name(mixer_build_t *state, int unitid, - int index, char *buf, int buflen) -{ - const struct usbmix_selector_map *p; - - if (! state->selector_map) - return 0; - for (p = state->selector_map; p->id; p++) { - if (p->id == unitid && index < p->count) - return strlcpy(buf, p->names[index], buflen); - } - return 0; -} - /* * find an audio control unit with the given unit id */ @@ -342,18 +301,16 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i int timeout = 10; while (timeout-- > 0) { - if (snd_usb_ctl_msg(cval->mixer->chip->dev, - usb_rcvctrlpipe(cval->mixer->chip->dev, 0), + if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, cval->mixer->ctrlif | (cval->id << 8), + validx, cval->ctrlif | (cval->id << 8), buf, val_len, 100) >= 0) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); return 0; } } - snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); + snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type); return -EINVAL; } @@ -382,15 +339,13 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i buf[0] = value_set & 0xff; buf[1] = (value_set >> 8) & 0xff; while (timeout -- > 0) - if (snd_usb_ctl_msg(cval->mixer->chip->dev, - usb_sndctrlpipe(cval->mixer->chip->dev, 0), + if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, cval->mixer->ctrlif | (cval->id << 8), + validx, cval->ctrlif | (cval->id << 8), buf, val_len, 100) >= 0) return 0; - snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); + snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); return -EINVAL; } @@ -430,22 +385,16 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou * if failed, give up and free the control instance. */ -static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl) +static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl) { - usb_mixer_elem_info_t *cval = kctl->private_data; int err; - - while (snd_ctl_find_id(state->chip->card, &kctl->id)) + while (snd_ctl_find_id(card, &kctl->id)) kctl->id.index++; - if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { + if ((err = snd_ctl_add(card, kctl)) < 0) { snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); snd_ctl_free_one(kctl); - return err; } - cval->elem_id = &kctl->id; - cval->next_id_elem = state->mixer->id_elems[cval->id]; - state->mixer->id_elems[cval->id] = cval; - return 0; + return err; } @@ -623,8 +572,10 @@ static struct usb_feature_control_info audio_feature_info[] = { /* private_free callback */ static void usb_mixer_elem_free(snd_kcontrol_t *kctl) { - kfree(kctl->private_data); - kctl->private_data = NULL; + if (kctl->private_data) { + kfree(kctl->private_data); + kctl->private_data = NULL; + } } @@ -657,8 +608,7 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min) } if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { - snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", - cval->id, cval->mixer->ctrlif, cval->control, cval->id); + snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id); return -EINVAL; } if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { @@ -718,7 +668,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &val); if (err < 0) { - if (cval->mixer->ignore_ctl_error) { + if (cval->chip->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } @@ -734,7 +684,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t /* master channel */ err = get_cur_mix_value(cval, 0, &val); if (err < 0) { - if (cval->mixer->ignore_ctl_error) { + if (cval->chip->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } @@ -760,7 +710,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &oval); if (err < 0) { - if (cval->mixer->ignore_ctl_error) + if (cval->chip->ignore_ctl_error) return 0; return err; } @@ -777,7 +727,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t } else { /* master channel */ err = get_cur_mix_value(cval, 0, &oval); - if (err < 0 && cval->mixer->ignore_ctl_error) + if (err < 0 && cval->chip->ignore_ctl_error) return 0; if (err < 0) return err; @@ -829,7 +779,8 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, snd_printk(KERN_ERR "cannot malloc kcontrol\n"); return; } - cval->mixer = state->mixer; + cval->chip = state->chip; + cval->ctrlif = state->ctrlif; cval->id = unitid; cval->control = control; cval->cmask = ctl_mask; @@ -904,21 +855,16 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ /* is not very clear from datasheets */ /* I hope that the min value is -15360 for newer firmware --jk */ - switch (state->chip->usb_id) { - case USB_ID(0x0471, 0x0101): - case USB_ID(0x0471, 0x0104): - case USB_ID(0x0471, 0x0105): - case USB_ID(0x0672, 0x1041): - if (!strcmp(kctl->id.name, "PCM Playback Volume") && - cval->min == -15616) { - snd_printk("using volume control quirk for the UDA1321/N101 chip\n"); - cval->max = -256; - } + if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) || + (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") && + cval->min == -15616) { + snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n"); + cval->max = -256; } snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); - add_control_to_empty(state, kctl); + add_control_to_empty(state->chip->card, kctl); } @@ -1001,7 +947,8 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, if (! cval) return; - cval->mixer = state->mixer; + cval->chip = state->chip; + cval->ctrlif = state->ctrlif; cval->id = unitid; cval->control = in_ch + 1; /* based on 1 */ cval->val_type = USB_MIXER_S16; @@ -1032,7 +979,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - add_control_to_empty(state, kctl); + add_control_to_empty(state->chip->card, kctl); } @@ -1095,7 +1042,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t int err, val; err = get_cur_ctl_value(cval, cval->control << 8, &val); - if (err < 0 && cval->mixer->ignore_ctl_error) { + if (err < 0 && cval->chip->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } @@ -1114,7 +1061,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) { - if (cval->mixer->ignore_ctl_error) + if (cval->chip->ignore_ctl_error) return 0; return err; } @@ -1232,6 +1179,9 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char } type = combine_word(&dsc[4]); + if (! type) + return 0; /* undefined? */ + for (info = list; info && info->type; info++) if (info->type == type) break; @@ -1249,7 +1199,8 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char snd_printk(KERN_ERR "cannot malloc kcontrol\n"); return -ENOMEM; } - cval->mixer = state->mixer; + cval->chip = state->chip; + cval->ctrlif = state->ctrlif; cval->id = unitid; cval->control = valinfo->control; cval->val_type = valinfo->val_type; @@ -1290,7 +1241,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - if ((err = add_control_to_empty(state, kctl)) < 0) + if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) return err; } return 0; @@ -1338,7 +1289,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t err = get_cur_ctl_value(cval, 0, &val); if (err < 0) { - if (cval->mixer->ignore_ctl_error) { + if (cval->chip->ignore_ctl_error) { ucontrol->value.enumerated.item[0] = 0; return 0; } @@ -1357,7 +1308,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t err = get_cur_ctl_value(cval, 0, &oval); if (err < 0) { - if (cval->mixer->ignore_ctl_error) + if (cval->chip->ignore_ctl_error) return 0; return err; } @@ -1435,7 +1386,8 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned snd_printk(KERN_ERR "cannot malloc kcontrol\n"); return -ENOMEM; } - cval->mixer = state->mixer; + cval->chip = state->chip; + cval->ctrlif = state->ctrlif; cval->id = unitid; cval->val_type = USB_MIXER_U8; cval->channels = 1; @@ -1463,9 +1415,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned kfree(cval); return -ENOMEM; } - len = check_mapped_selector_name(state, unitid, i, namelist[i], - MAX_ITEM_NAME_LEN); - if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0) + if (check_input_term(state, desc[5 + i], &iterm) >= 0) len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); if (! len) sprintf(namelist[i], "Input %d", i); @@ -1500,7 +1450,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", cval->id, kctl->id.name, num_ins); - if ((err = add_control_to_empty(state, kctl)) < 0) + if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) return err; return 0; @@ -1543,55 +1493,41 @@ static int parse_audio_unit(mixer_build_t *state, int unitid) } } -static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) -{ - kfree(mixer->id_elems); - if (mixer->urb) { - kfree(mixer->urb->transfer_buffer); - usb_free_urb(mixer->urb); - } - if (mixer->rc_urb) - usb_free_urb(mixer->rc_urb); - kfree(mixer->rc_setup_packet); - kfree(mixer); -} - -static int snd_usb_mixer_dev_free(snd_device_t *device) -{ - struct usb_mixer_interface *mixer = device->device_data; - snd_usb_mixer_free(mixer); - return 0; -} - /* * create mixer controls * * walk through all OUTPUT_TERMINAL descriptors to search for mixers */ -static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) +int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) { unsigned char *desc; mixer_build_t state; int err; const struct usbmix_ctl_map *map; - struct usb_host_interface *hostif; + struct usb_device_descriptor *dev = &chip->dev->descriptor; + struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; + + strcpy(chip->card->mixername, "USB Mixer"); - hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; memset(&state, 0, sizeof(state)); - state.chip = mixer->chip; - state.mixer = mixer; + state.chip = chip; state.buffer = hostif->extra; state.buflen = hostif->extralen; + state.ctrlif = ctrlif; + state.vendor = le16_to_cpu(dev->idVendor); + state.product = le16_to_cpu(dev->idProduct); /* check the mapping table */ - for (map = usbmix_ctl_maps; map->id; map++) { - if (map->id == state.chip->usb_id) { + for (map = usbmix_ctl_maps; map->vendor; map++) { + if (map->vendor == state.vendor && map->product == state.product) { state.map = map->map; - state.selector_map = map->selector_map; - mixer->ignore_ctl_error = map->ignore_ctl_error; + chip->ignore_ctl_error = map->ignore_ctl_error; break; } } +#ifdef IGNORE_CTL_ERROR + chip->ignore_ctl_error = 1; +#endif desc = NULL; while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { @@ -1607,393 +1543,3 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) } return 0; } - -static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, - int unitid) -{ - usb_mixer_elem_info_t *info; - - for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - info->elem_id); -} - -static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, - int unitid) -{ - if (mixer->rc_type == RC_NONE) - return; - /* unit ids specific to Extigy/Audigy 2 NX: */ - switch (unitid) { - case 0: /* remote control */ - mixer->rc_urb->dev = mixer->chip->dev; - usb_submit_urb(mixer->rc_urb, GFP_ATOMIC); - break; - case 4: /* digital in jack */ - case 7: /* line in jacks */ - case 19: /* speaker out jacks */ - case 20: /* headphones out jack */ - break; - default: - snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); - break; - } -} - -static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs) -{ - struct usb_mixer_interface *mixer = urb->context; - - if (urb->status == 0) { - u8 *buf = urb->transfer_buffer; - int i; - - for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) { - snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", - buf[0], buf[1]); - /* ignore any notifications not from the control interface */ - if ((buf[0] & 0x0f) != 0) - continue; - if (!(buf[0] & 0x40)) - snd_usb_mixer_notify_id(mixer, buf[1]); - else - snd_usb_mixer_memory_change(mixer, buf[1]); - } - } - if (urb->status != -ENOENT && urb->status != -ECONNRESET) { - urb->dev = mixer->chip->dev; - usb_submit_urb(urb, GFP_ATOMIC); - } -} - -/* create the handler for the optional status interrupt endpoint */ -static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) -{ - struct usb_host_interface *hostif; - struct usb_endpoint_descriptor *ep; - void *transfer_buffer; - int buffer_length; - unsigned int epnum; - - hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; - /* we need one interrupt input endpoint */ - if (get_iface_desc(hostif)->bNumEndpoints < 1) - return 0; - ep = get_endpoint(hostif, 0); - if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN || - (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) - return 0; - - epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - buffer_length = le16_to_cpu(ep->wMaxPacketSize); - transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!transfer_buffer) - return -ENOMEM; - mixer->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mixer->urb) { - kfree(transfer_buffer); - return -ENOMEM; - } - usb_fill_int_urb(mixer->urb, mixer->chip->dev, - usb_rcvintpipe(mixer->chip->dev, epnum), - transfer_buffer, buffer_length, - snd_usb_mixer_status_complete, mixer, ep->bInterval); - usb_submit_urb(mixer->urb, GFP_KERNEL); - return 0; -} - -static void snd_usb_soundblaster_remote_complete(struct urb *urb, - struct pt_regs *regs) -{ - struct usb_mixer_interface *mixer = urb->context; - /* - * format of remote control data: - * Extigy: xx 00 - * Audigy 2 NX: 06 80 xx 00 00 00 - */ - int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; - u32 code; - - if (urb->status < 0 || urb->actual_length <= offset) - return; - code = mixer->rc_buffer[offset]; - /* the Mute button actually changes the mixer control */ - if (code == 13) - snd_usb_mixer_notify_id(mixer, 18); - mixer->rc_code = code; - wmb(); - wake_up(&mixer->rc_waitq); -} - -static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file) -{ - struct usb_mixer_interface *mixer = hw->private_data; - - if (test_and_set_bit(0, &mixer->rc_hwdep_open)) - return -EBUSY; - return 0; -} - -static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file) -{ - struct usb_mixer_interface *mixer = hw->private_data; - - clear_bit(0, &mixer->rc_hwdep_open); - smp_mb__after_clear_bit(); - return 0; -} - -static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf, - long count, loff_t *offset) -{ - struct usb_mixer_interface *mixer = hw->private_data; - int err; - u32 rc_code; - - if (count != 1 && count != 4) - return -EINVAL; - err = wait_event_interruptible(mixer->rc_waitq, - (rc_code = xchg(&mixer->rc_code, 0)) != 0); - if (err == 0) { - if (count == 1) - err = put_user(rc_code, buf); - else - err = put_user(rc_code, (u32 __user *)buf); - } - return err < 0 ? err : count; -} - -static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file, - poll_table *wait) -{ - struct usb_mixer_interface *mixer = hw->private_data; - - poll_wait(file, &mixer->rc_waitq, wait); - return mixer->rc_code ? POLLIN | POLLRDNORM : 0; -} - -static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) -{ - snd_hwdep_t *hwdep; - int err, len; - - switch (mixer->chip->usb_id) { - case USB_ID(0x041e, 0x3000): - mixer->rc_type = RC_EXTIGY; - len = 2; - break; - case USB_ID(0x041e, 0x3020): - mixer->rc_type = RC_AUDIGY2NX; - len = 6; - break; - default: - return 0; - } - - init_waitqueue_head(&mixer->rc_waitq); - err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); - if (err < 0) - return err; - snprintf(hwdep->name, sizeof(hwdep->name), - "%s remote control", mixer->chip->card->shortname); - hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; - hwdep->private_data = mixer; - hwdep->ops.read = snd_usb_sbrc_hwdep_read; - hwdep->ops.open = snd_usb_sbrc_hwdep_open; - hwdep->ops.release = snd_usb_sbrc_hwdep_release; - hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; - - mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mixer->rc_urb) - return -ENOMEM; - mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL); - if (!mixer->rc_setup_packet) { - usb_free_urb(mixer->rc_urb); - mixer->rc_urb = NULL; - return -ENOMEM; - } - mixer->rc_setup_packet->bRequestType = - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - mixer->rc_setup_packet->bRequest = GET_MEM; - mixer->rc_setup_packet->wValue = cpu_to_le16(0); - mixer->rc_setup_packet->wIndex = cpu_to_le16(0); - mixer->rc_setup_packet->wLength = cpu_to_le16(len); - usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), - (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len, - snd_usb_soundblaster_remote_complete, mixer); - return 0; -} - -static int snd_audigy2nx_led_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_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - - ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index]; - return 0; -} - -static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - int value = ucontrol->value.integer.value[0]; - int err, changed; - - if (value > 1) - return -EINVAL; - changed = value != mixer->audigy2nx_leds[index]; - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - value, index + 2, NULL, 0, 100); - if (err < 0) - return err; - mixer->audigy2nx_leds[index] = value; - return changed; -} - -static snd_kcontrol_new_t snd_audigy2nx_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CMSS LED Switch", - .info = snd_audigy2nx_led_info, - .get = snd_audigy2nx_led_get, - .put = snd_audigy2nx_led_put, - .private_value = 0, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Power LED Switch", - .info = snd_audigy2nx_led_info, - .get = snd_audigy2nx_led_get, - .put = snd_audigy2nx_led_put, - .private_value = 1, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Dolby Digital LED Switch", - .info = snd_audigy2nx_led_info, - .get = snd_audigy2nx_led_get, - .put = snd_audigy2nx_led_put, - .private_value = 2, - }, -}; - -static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) -{ - int i, err; - - for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { - err = snd_ctl_add(mixer->chip->card, - snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); - if (err < 0) - return err; - } - mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */ - return 0; -} - -static void snd_audigy2nx_proc_read(snd_info_entry_t *entry, - snd_info_buffer_t *buffer) -{ - static const struct { - int unitid; - const char *name; - } jacks[] = { - {4, "dig in "}, - {7, "line in"}, - {19, "spk out"}, - {20, "hph out"}, - }; - struct usb_mixer_interface *mixer = entry->private_data; - int i, err; - u8 buf[3]; - - snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); - for (i = 0; i < ARRAY_SIZE(jacks); ++i) { - snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), - GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, - jacks[i].unitid << 8, buf, 3, 100); - if (err == 3 && buf[0] == 3) - snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); - else - snd_iprintf(buffer, "?\n"); - } -} - -int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) -{ - static snd_device_ops_t dev_ops = { - .dev_free = snd_usb_mixer_dev_free - }; - struct usb_mixer_interface *mixer; - int err; - - strcpy(chip->card->mixername, "USB Mixer"); - - mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL); - if (!mixer) - return -ENOMEM; - mixer->chip = chip; - mixer->ctrlif = ctrlif; -#ifdef IGNORE_CTL_ERROR - mixer->ignore_ctl_error = 1; -#endif - mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL); - if (!mixer->id_elems) { - kfree(mixer); - return -ENOMEM; - } - - if ((err = snd_usb_mixer_controls(mixer)) < 0 || - (err = snd_usb_mixer_status_create(mixer)) < 0) - goto _error; - - if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) - goto _error; - - if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) { - snd_info_entry_t *entry; - - if ((err = snd_audigy2nx_controls_create(mixer)) < 0) - goto _error; - if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) - snd_info_set_text_ops(entry, mixer, 1024, - snd_audigy2nx_proc_read); - } - - err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); - if (err < 0) - goto _error; - list_add(&mixer->list, &chip->mixer_list); - return 0; - -_error: - snd_usb_mixer_free(mixer); - return err; -} - -void snd_usb_mixer_disconnect(struct list_head *p) -{ - struct usb_mixer_interface *mixer; - - mixer = list_entry(p, struct usb_mixer_interface, list); - if (mixer->urb) - usb_kill_urb(mixer->urb); - if (mixer->rc_urb) - usb_kill_urb(mixer->rc_urb); -} diff --git a/trunk/sound/usb/usbmixer_maps.c b/trunk/sound/usb/usbmixer_maps.c index f05500b05ec0..c69b4b0875f8 100644 --- a/trunk/sound/usb/usbmixer_maps.c +++ b/trunk/sound/usb/usbmixer_maps.c @@ -26,16 +26,10 @@ struct usbmix_name_map { int control; }; -struct usbmix_selector_map { - int id; - int count; - const char **names; -}; - struct usbmix_ctl_map { - u32 id; + int vendor; + int product; const struct usbmix_name_map *map; - const struct usbmix_selector_map *selector_map; int ignore_ctl_error; }; @@ -97,96 +91,6 @@ static struct usbmix_name_map extigy_map[] = { { 0 } /* terminator */ }; -/* Sound Blaster MP3+ controls mapping - * The default mixer channels have totally misleading names, - * e.g. no Master and fake PCM volume - * Pavel Mihaylov - */ -static struct usbmix_name_map mp3plus_map[] = { - /* 1: IT pcm */ - /* 2: IT mic */ - /* 3: IT line */ - /* 4: IT digital in */ - /* 5: OT digital out */ - /* 6: OT speaker */ - /* 7: OT pcm capture */ - { 8, "Capture Input Source" }, /* FU, default PCM Capture Source */ - /* (Mic, Input 1 = Line input, Input 2 = Optical input) */ - { 9, "Master Playback" }, /* FU, default Speaker 1 */ - /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */ - /* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */ - { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */ - { 11, "Line Capture" }, /* FU, default PCM Capture */ - { 12, "Digital In Playback" }, /* FU, default PCM 1 */ - /* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */ - { 14, "Line Playback" }, /* FU, default Speaker */ - /* 15: MU */ - { 0 } /* terminator */ -}; - -/* Topology of SB Audigy 2 NX - - +----------------------------->EU[27]--+ - | v - | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24] - | | ^ -USB_IN[1]-+------------+ +->EU[17]->+->FU[11]-+ - | v | v | -Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20] - | ^ | | -Lin_IN[7]-+--->FU[8]---+ +->EU[23]->FU[28]------------->Spk_OUT[19] - | | v - +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15] - | ^ - +->FU[13]--------------------------------------+ -*/ -static struct usbmix_name_map audigy2nx_map[] = { - /* 1: IT pcm playback */ - /* 4: IT digital in */ - { 6, "Digital In Playback" }, /* FU */ - /* 7: IT line in */ - { 8, "Line Playback" }, /* FU */ - { 11, "What-U-Hear Capture" }, /* FU */ - { 12, "Line Capture" }, /* FU */ - { 13, "Digital In Capture" }, /* FU */ - { 14, "Capture Source" }, /* SU */ - /* 15: OT pcm capture */ - /* 16: MU w/o controls */ - { 17, NULL }, /* DISABLED: EU (for what?) */ - { 18, "Master Playback" }, /* FU */ - /* 19: OT speaker */ - /* 20: OT headphone */ - { 21, NULL }, /* DISABLED: EU (for what?) */ - { 22, "Digital Out Playback" }, /* FU */ - { 23, NULL }, /* DISABLED: EU (for what?) */ - /* 24: OT digital out */ - { 27, NULL }, /* DISABLED: EU (for what?) */ - { 28, "Speaker Playback" }, /* FU */ - { 29, "Digital Out Source" }, /* SU */ - { 30, "Headphone Playback" }, /* FU */ - { 31, "Headphone Source" }, /* SU */ - { 0 } /* terminator */ -}; - -static struct usbmix_selector_map audigy2nx_selectors[] = { - { - .id = 14, /* Capture Source */ - .count = 3, - .names = (const char*[]) {"Line", "Digital In", "What-U-Hear"} - }, - { - .id = 29, /* Digital Out Source */ - .count = 3, - .names = (const char*[]) {"Front", "PCM", "Digital In"} - }, - { - .id = 31, /* Headphone Source */ - .count = 2, - .names = (const char*[]) {"Front", "Side"} - }, - { 0 } /* terminator */ -}; - /* LineX FM Transmitter entry - needed to bypass controls bug */ static struct usbmix_name_map linex_map[] = { /* 1: IT pcm */ @@ -223,29 +127,9 @@ static struct usbmix_name_map justlink_map[] = { */ static struct usbmix_ctl_map usbmix_ctl_maps[] = { - { - .id = USB_ID(0x041e, 0x3000), - .map = extigy_map, - .ignore_ctl_error = 1, - }, - { - .id = USB_ID(0x041e, 0x3010), - .map = mp3plus_map, - }, - { - .id = USB_ID(0x041e, 0x3020), - .map = audigy2nx_map, - .selector_map = audigy2nx_selectors, - }, - { - .id = USB_ID(0x08bb, 0x2702), - .map = linex_map, - .ignore_ctl_error = 1, - }, - { - .id = USB_ID(0x0c45, 0x1158), - .map = justlink_map, - }, + { 0x41e, 0x3000, extigy_map, 1 }, + { 0x8bb, 0x2702, linex_map, 1 }, + { 0xc45, 0x1158, justlink_map, 0 }, { 0 } /* terminator */ }; diff --git a/trunk/sound/usb/usbquirks.h b/trunk/sound/usb/usbquirks.h index f5135641b3e2..88bbd944d4be 100644 --- a/trunk/sound/usb/usbquirks.h +++ b/trunk/sound/usb/usbquirks.h @@ -203,28 +203,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-4", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x000f, + .in_cables = 0x000f } } }, @@ -233,28 +216,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SC-8850", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x003f, - .in_cables = 0x003f - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x003f, + .in_cables = 0x003f } } }, @@ -263,28 +229,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "U-8", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0005, - .in_cables = 0x0005 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0005, + .in_cables = 0x0005 } } }, @@ -293,28 +242,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-2", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0003, + .in_cables = 0x0003 } } }, @@ -323,28 +255,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SC-8820", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0013, - .in_cables = 0x0013 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0013, + .in_cables = 0x0013 } } }, @@ -353,28 +268,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "PC-300", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 } } }, @@ -383,28 +281,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-1", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 } } }, @@ -413,28 +294,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SK-500", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0013, - .in_cables = 0x0013 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0013, + .in_cables = 0x0013 } } }, @@ -557,28 +421,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "SD-90", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x000f, + .in_cables = 0x000f } } }, @@ -587,28 +434,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "MMP-2", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 } } }, @@ -779,33 +609,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - /* - * This quirk is for the "Advanced Driver" mode. If off, the GS-10 - * has ID 0x003c and is standard compliant, but has only 16-bit PCM - * and no MIDI. - */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "BOSS", .product_name = "GS-10", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const snd_usb_audio_quirk_t[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + .ifnum = 3, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0003, + .in_cables = 0x0003 } } }, diff --git a/trunk/sound/usb/usx2y/usbusx2y.c b/trunk/sound/usb/usx2y/usbusx2y.c index e6e6da159671..89ee8b732013 100644 --- a/trunk/sound/usb/usx2y/usbusx2y.c +++ b/trunk/sound/usb/usx2y/usbusx2y.c @@ -442,7 +442,7 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr) snd_card_disconnect((snd_card_t*)ptr); /* release the midi resources */ list_for_each(p, &usX2Y->chip.midi_list) { - snd_usbmidi_disconnect(p); + snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver); } if (usX2Y->us428ctls_sharedmem) wake_up(&usX2Y->us428ctls_wait_queue_head); diff --git a/trunk/sound/usb/usx2y/usbusx2yaudio.c b/trunk/sound/usb/usx2y/usbusx2yaudio.c index 62dfd28b3b07..4c292e090069 100644 --- a/trunk/sound/usb/usx2y/usbusx2yaudio.c +++ b/trunk/sound/usb/usx2y/usbusx2yaudio.c @@ -401,8 +401,10 @@ static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs) for (i = 0; i < NRURBS; i++) usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); - kfree(subs->tmpbuf); - subs->tmpbuf = NULL; + if (subs->tmpbuf) { + kfree(subs->tmpbuf); + subs->tmpbuf = NULL; + } } /* * initialize a substream's urbs