diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 10:58:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 10:58:37 -0700 |
commit | 1c15ca4e4efaddb78f83eed31eeee34c522c3ae2 (patch) | |
tree | a528054028d13fb3361ec72663c7fce7b619564b /sound/pci | |
parent | 34b62f186db9614e55d021f8c58d22fc44c57911 (diff) | |
parent | baa6584a24494fbbd2862270d39e61b86987cc91 (diff) | |
download | linux-stable-1c15ca4e4efaddb78f83eed31eeee34c522c3ae2.tar.gz linux-stable-1c15ca4e4efaddb78f83eed31eeee34c522c3ae2.tar.bz2 linux-stable-1c15ca4e4efaddb78f83eed31eeee34c522c3ae2.zip |
Merge tag 'sound-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"At this time, it's an interesting mixture of changes for both old and
new stuff. Majority of changes are about ASoC (lots of systematic
changes for converting remove callbacks to void, and cleanups), while
we got the fixes and the enhancements of very old PCI cards, too.
Here are some highlights:
ALSA/ASoC Core:
- Continued effort of more ASoC core cleanups
- Minor improvements for XRUN handling in indirect PCM helpers
- Code refactoring of PCM core code
ASoC:
- Continued feature and simplification work on SOF, including
addition of a no-DSP mode for bringup, HDA MLink and extensions to
the IPC4 protocol
- Hibernation support for CS35L45
- More DT binding conversions
- Support for Cirrus Logic CS35L56, Freescale QMC, Maxim MAX98363,
nVidia systems with MAX9809x and RT5631, Realtek RT712, Renesas
R-Car Gen4, Rockchip RK3588 and TI TAS5733
ALSA:
- Lots of works for legacy emu10k1 and ymfpci PCI drivers
- PCM kselftest fixes and enhancements"
* tag 'sound-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (586 commits)
ALSA: emu10k1: use high-level I/O in set_filterQ()
ALSA: emu10k1: use high-level I/O functions also during init
ALSA: emu10k1: fix error handling in snd_audigy_i2c_volume_put()
ALSA: emu10k1: don't stop DSP in _snd_emu10k1_{,audigy_}init_efx()
ALSA: emu10k1: fix SNDRV_EMU10K1_IOCTL_SINGLE_STEP
ALSA: emu10k1: skip Sound Blaster-specific hacks for E-MU cards
ALSA: emu10k1: fixup DSP defines
ALSA: emu10k1: pull in some register definitions from kX-project
ALSA: emu10k1: remove some bogus defines
ALSA: emu10k1: eliminate some unused defines
ALSA: emu10k1: fix lineup of EMU_HANA_* defines
ALSA: emu10k1: comment updates
ALSA: emu10k1: fix snd_emu1010_fpga_read() input masking for rev2 cards
ALSA: emu10k1: remove unused emu->pcm_playback_efx_substream field
ALSA: emu10k1: remove unused `resume` parameter from snd_emu10k1_init()
ALSA: emu10k1: minor optimizations
ALSA: emu10k1: remove remaining cruft from snd_emu10k1_emu1010_init()
ALSA: emu10k1: remove apparently pointless EMU_HANA_OPTION_CARDS reads
ALSA: emu10k1: remove apparently pointless FPGA reads
ALSA: emu10k1: stop doing weird things with HCFG in snd_emu10k1_emu1010_init()
...
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/Kconfig | 4 | ||||
-rw-r--r-- | sound/pci/asihpi/hpi6000.c | 2 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1.c | 11 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_callback.c | 5 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 256 | ||||
-rw-r--r-- | sound/pci/emu10k1/emufx.c | 69 | ||||
-rw-r--r-- | sound/pci/emu10k1/emumixer.c | 45 | ||||
-rw-r--r-- | sound/pci/emu10k1/emupcm.c | 80 | ||||
-rw-r--r-- | sound/pci/emu10k1/emuproc.c | 5 | ||||
-rw-r--r-- | sound/pci/emu10k1/io.c | 61 | ||||
-rw-r--r-- | sound/pci/emu10k1/irq.c | 32 | ||||
-rw-r--r-- | sound/pci/emu10k1/p16v.c | 113 | ||||
-rw-r--r-- | sound/pci/emu10k1/p16v.h | 2 | ||||
-rw-r--r-- | sound/pci/emu10k1/p17v.h | 4 | ||||
-rw-r--r-- | sound/pci/hda/cs35l41_hda.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 12 | ||||
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 6 | ||||
-rw-r--r-- | sound/pci/ymfpci/ymfpci.c | 39 | ||||
-rw-r--r-- | sound/pci/ymfpci/ymfpci.h | 54 | ||||
-rw-r--r-- | sound/pci/ymfpci/ymfpci_main.c | 79 |
22 files changed, 355 insertions, 539 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index a55836225401..861958451ef5 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -461,7 +461,7 @@ config SND_INDIGODJX will be called snd-indigodjx config SND_EMU10K1 - tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" + tristate "Emu10k1 (SB Live!, Audigy, E-MU APS/0404/1010/1212/1616/1820)" select FW_LOADER select SND_HWDEP select SND_RAWMIDI @@ -471,7 +471,7 @@ config SND_EMU10K1 depends on ZONE_DMA help Say Y to include support for Sound Blaster PCI 512, Live!, - Audigy and E-mu APS (partially supported) soundcards. + Audigy and E-MU APS/0404/1010/1212/1616/1820 soundcards. The confusing multitude of mixer controls is documented in <file:Documentation/sound/cards/sb-live-mixer.rst> and diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 88d902997b74..72aa135d69f8 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c @@ -1253,7 +1253,6 @@ static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, int local_count = count; int xfer_size; u32 *pdata = dest; - u32 loop_count = 0; while (local_count) { if (local_count > c6711_burst_size) @@ -1273,7 +1272,6 @@ static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, pdata += xfer_size; local_hpi_address += sizeof(u32) * xfer_size; local_count -= xfer_size; - loop_count++; } if (time_out) diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 672af4b9597b..b8163f26004a 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -68,17 +68,6 @@ static const struct pci_device_id snd_emu10k1_ids[] = { { 0, } }; -/* - * Audigy 2 Value notes: - * A_IOCFG Input (GPIO) - * 0x400 = Front analog jack plugged in. (Green socket) - * 0x1000 = Read analog jack plugged in. (Black socket) - * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) - * A_IOCFG Output (GPIO) - * 0x60 = Sound out of front Left. - * Win sets it to 0xXX61 - */ - MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); static int snd_card_emu10k1_probe(struct pci_dev *pci, diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index dba1e9fc2eec..c6d152575181 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -531,8 +531,5 @@ set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) { - unsigned int val; - val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE; - val |= (vp->reg.parm.filterQ << 28); - snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val); + snd_emu10k1_ptr_write(hw, CCCA_RESONANCE, vp->ch, vp->reg.parm.filterQ); } diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 3880f359e688..3abdaf1b9624 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -140,7 +140,7 @@ static const unsigned int i2c_adc_init[][2] = { { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ }; -static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) +static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir) { unsigned int silent_page; int ch; @@ -162,6 +162,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) outl(0, emu->port + INTE); snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); + + /* disable stop on loop end */ snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); @@ -181,13 +183,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]); snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]); - if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ + if (emu->card_capabilities->emu_model) { + } else if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ /* Hacks for Alice3 to work independent of haP16V driver */ /* Setup SRCMulti_I2S SamplingRate */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp &= 0xfffff1ff; - tmp |= (0x2<<9); - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); + snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, 0, A_I2S_CAPTURE_96000); /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); @@ -199,32 +199,26 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) outl(0x0201, emu->port + HCFG2); /* Set playback routing. */ snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); - } - if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ + } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ /* Hacks for Alice3 to work independent of haP16V driver */ dev_info(emu->card->dev, "Audigy2 value: Special config.\n"); /* Setup SRCMulti_I2S SamplingRate */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp &= 0xfffff1ff; - tmp |= (0x2<<9); - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); + snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, 0, A_I2S_CAPTURE_96000); /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ - outl(0x600000, emu->port + 0x20); - outl(0x14, emu->port + 0x24); + snd_emu10k1_ptr20_write(emu, P17V_SRCSel, 0, 0x14); /* Setup SRCMulti Input Audio Enable */ - outl(0x7b0000, emu->port + 0x20); - outl(0xFF000000, emu->port + 0x24); + snd_emu10k1_ptr20_write(emu, P17V_MIXER_I2S_ENABLE, 0, 0xFF000000); /* Setup SPDIF Out Audio Enable */ /* The Audigy 2 Value has a separate SPDIF out, * so no need for a mixer switch */ - outl(0x7a0000, emu->port + 0x20); - outl(0xFF000000, emu->port + 0x24); - tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ - outl(tmp, emu->port + A_IOCFG); + snd_emu10k1_ptr20_write(emu, P17V_MIXER_SPDIF_ENABLE, 0, 0xFF000000); + + tmp = inw(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ + outw(tmp, emu->port + A_IOCFG); } if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */ int size, n; @@ -244,15 +238,15 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) * GPIO6: Unknown * GPIO7: Unknown */ - outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ + outw(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ } if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ int size, n; snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f); - tmp = inl(emu->port + A_IOCFG); - outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */ - tmp = inl(emu->port + A_IOCFG); + tmp = inw(emu->port + A_IOCFG); + outw(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */ + tmp = inw(emu->port + A_IOCFG); size = ARRAY_SIZE(i2c_adc_init); for (n = 0; n < size; n++) snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); @@ -308,12 +302,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) } else if (emu->card_capabilities->i2c_adc) { ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ } else if (emu->audigy) { - unsigned int reg = inl(emu->port + A_IOCFG); - outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); + u16 reg = inw(emu->port + A_IOCFG); + outw(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); udelay(500); - outl(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG); + outw(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG); udelay(100); - outl(reg, emu->port + A_IOCFG); + outw(reg, emu->port + A_IOCFG); } else { unsigned int reg = inl(emu->port + HCFG); outl(reg | HCFG_GPOUT2, emu->port + HCFG); @@ -329,8 +323,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) } else if (emu->card_capabilities->i2c_adc) { ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ } else if (emu->audigy) { /* enable analog output */ - unsigned int reg = inl(emu->port + A_IOCFG); - outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); + u16 reg = inw(emu->port + A_IOCFG); + outw(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); } if (emu->address_mode == 0) { @@ -354,19 +348,19 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) } else if (emu->card_capabilities->i2c_adc) { ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ } else if (emu->audigy) { - outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); + outw(inw(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ /* Unmute Analog now. Set GPO6 to 1 for Apollo. * This has to be done after init ALice3 I2SOut beyond 48KHz. * So, sequence is important. */ - outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); + outw(inw(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ /* Unmute Analog now. */ - outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); + outw(inw(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); } else { /* Disable routing from AC97 line out to Front speakers */ - outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); + outw(inw(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); } } @@ -651,26 +645,27 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, const struct firmware *fw_entry) { int n, i; - int reg; - int value; - __always_unused unsigned int write_post; + u16 reg; + u8 value; + __always_unused u16 write_post; unsigned long flags; if (!fw_entry) return -EIO; /* The FPGA is a Xilinx Spartan IIE XC2S50E */ + /* On E-MU 0404b it is a Xilinx Spartan III XC3S50 */ /* GPIO7 -> FPGA PGMN * GPIO6 -> FPGA CCLK * GPIO5 -> FPGA DIN * FPGA CONFIG OFF -> FPGA PGMN */ spin_lock_irqsave(&emu->emu_lock, flags); - outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */ - write_post = inl(emu->port + A_IOCFG); + outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */ + write_post = inw(emu->port + A_GPIO); udelay(100); - outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ - write_post = inl(emu->port + A_IOCFG); + outw(0x80, emu->port + A_GPIO); /* Leave bit 7 set during netlist setup. */ + write_post = inw(emu->port + A_GPIO); udelay(100); /* Allow FPGA memory to clean */ for (n = 0; n < fw_entry->size; n++) { value = fw_entry->data[n]; @@ -679,15 +674,15 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, if (value & 0x1) reg = reg | 0x20; value = value >> 1; - outl(reg, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - outl(reg | 0x40, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); + outw(reg, emu->port + A_GPIO); + write_post = inw(emu->port + A_GPIO); + outw(reg | 0x40, emu->port + A_GPIO); + write_post = inw(emu->port + A_GPIO); } } /* After programming, set GPIO bit 4 high again. */ - outl(0x10, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); + outw(0x10, emu->port + A_GPIO); + write_post = inw(emu->port + A_GPIO); spin_unlock_irqrestore(&emu->emu_lock, flags); return 0; @@ -782,7 +777,7 @@ static void emu1010_firmware_work(struct work_struct *work) } else if (!reg && emu->emu1010.last_reg) { /* Audio Dock removed */ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); - /* Unmute all */ + /* The hardware auto-mutes all, so we unmute again */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } @@ -794,29 +789,6 @@ static void emu1010_firmware_work(struct work_struct *work) } /* - * EMU-1010 - details found out from this driver, official MS Win drivers, - * testing the card: - * - * Audigy2 (aka Alice2): - * --------------------- - * * communication over PCI - * * conversion of 32-bit data coming over EMU32 links from HANA FPGA - * to 2 x 16-bit, using internal DSP instructions - * * slave mode, clock supplied by HANA - * * linked to HANA using: - * 32 x 32-bit serial EMU32 output channels - * 16 x EMU32 input channels - * (?) x I2S I/O channels (?) - * - * FPGA (aka HANA): - * --------------- - * * provides all (?) physical inputs and outputs of the card - * (ADC, DAC, SPDIF I/O, ADAT I/O, etc.) - * * provides clock signal for the card and Alice2 - * * two crystals - for 44.1kHz and 48kHz multiples - * * provides internal routing of signal sources to signal destinations - * * inputs/outputs to Alice2 - see above - * * Current status of the driver: * ---------------------------- * * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz) @@ -831,24 +803,10 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) int err; dev_info(emu->card->dev, "emu1010: Special config.\n"); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0005a00c, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0005a004, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Mute all codecs. - */ - outl(0x0005a000, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Mute all codecs. - */ - outl(0x0005a000, emu->port + HCFG); + + /* Mute, and disable audio and lock cache, just in case. + * Proper init follows in snd_emu10k1_init(). */ + outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); /* Disable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); @@ -897,34 +855,20 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); /* Optical -> ADAT I/O */ - /* 0 : SPDIF - * 1 : ADAT - */ emu->emu1010.optical_in = 1; /* IN_ADAT */ - emu->emu1010.optical_out = 1; /* IN_ADAT */ - tmp = 0; + emu->emu1010.optical_out = 1; /* OUT_ADAT */ tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); - snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp); /* Set no attenuation on Audio Dock pads. */ snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); emu->emu1010.adc_pads = 0x00; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); /* Unmute Audio dock DACs, Headphone source DAC-4. */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); - snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp); /* DAC PADs. */ snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); emu->emu1010.dac_pads = 0x0f; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* MIDI routing */ @@ -936,8 +880,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) /* IRQ Enable: All off */ snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - dev_info(emu->card->dev, "emu1010: Card options3 = 0x%x\n", reg); + emu->emu1010.internal_clock = 1; /* 48000 */ /* Default WCLK set to 48kHz. */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); /* Word Clock source, Internal 48kHz x1 */ @@ -1073,29 +1016,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0000a000, emu->port + HCFG); - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Un-Mute all codecs. - */ - outl(0x0000a001, emu->port + HCFG); - - /* Initial boot complete. Now patches */ - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ - #if 0 snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ @@ -1215,21 +1135,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); emu->emu1010.output_source[23] = 28; } - /* TEMP: Select SPDIF in/out */ - /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */ - - /* TEMP: Select 48kHz SPDIF out */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); - /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ - emu->emu1010.internal_clock = 1; /* 48000 */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ - /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */ - /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */ - /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */ return 0; } @@ -1343,6 +1248,15 @@ static const struct snd_emu_chip_details emu_chip_details[] = { * AC97: STAC9750 * CA0151: None */ + /* + * A_IOCFG Input (GPIO) + * 0x400 = Front analog jack plugged in. (Green socket) + * 0x1000 = Rear analog jack plugged in. (Black socket) + * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) + * A_IOCFG Output (GPIO) + * 0x60 = Sound out of front Left. + * Win sets it to 0xXX61 + */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", .id = "Audigy2", @@ -1391,6 +1305,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .spi_dac = 1, .i2c_adc = 1, .spk71 = 1} , + /* This is MAEM8950 "Mana" */ + /* Attach MicroDock[M] to make it an E-MU 1616[m]. */ + /* Does NOT support sync daughter card (obviously). */ /* Tested by James@superbug.co.uk 4th Nov 2007. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", @@ -1401,7 +1318,10 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .spk71 = 1 , .emu_model = EMU_MODEL_EMU1616}, /* Tested by James@superbug.co.uk 4th Nov 2007. */ - /* This is MAEM8960, 0202 is MAEM 8980 */ + /* This is MAEM8960 "Hana3", 0202 is MAEM8980 */ + /* Attach 0202 daughter card to make it an E-MU 1212m, OR a + * MicroDock[M] to make it an E-MU 1616[m]. */ + /* Does NOT support sync daughter card. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", .id = "EMU1010", @@ -1411,6 +1331,11 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */ /* This is MAEM8986, 0202 is MAEM8980 */ + /* Attach 0202 daughter card to make it an E-MU 1212m, OR a + * MicroDockM to make it an E-MU 1616m. The non-m + * version was never sold with this card, but should + * still work. */ + /* Does NOT support sync daughter card. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", .id = "EMU1010", @@ -1419,7 +1344,10 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .spk71 = 1, .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ /* Tested by James@superbug.co.uk 8th July 2005. */ - /* This is MAEM8810, 0202 is MAEM8820 */ + /* This is MAEM8810 "Hana", 0202 is MAEM8820 "Hamoa" */ + /* Attach 0202 daughter card to make it an E-MU 1212m, OR an + * AudioDock[M] to make it an E-MU 1820[m]. */ + /* Supports sync daughter card. */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", .id = "EMU1010", @@ -1427,7 +1355,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ - /* EMU0404b */ + /* This is MAEM8852 "HanaLiteLite" */ + /* Supports sync daughter card. */ + /* Tested by oswald.buddenhagen@gmx.de Mar 2023. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", .id = "EMU0404", @@ -1435,6 +1365,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ + /* This is MAEM8850 "HanaLite" */ + /* Supports sync daughter card. */ /* Tested by James@superbug.co.uk 20-3-2007. */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", @@ -1444,6 +1376,7 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ /* EMU0404 PCIe */ + /* Does NOT support sync daughter card. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", .id = "EMU0404", @@ -1451,7 +1384,6 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ - /* Note that all E-mu cards require kernel 2.6 or newer. */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", .id = "Audigy2", @@ -1532,6 +1464,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .spdif_bug = 1, .adc_1361t = 1, /* 24 bit capture instead of 16bit */ .ac97_chip = 1} , + /* Audigy 2 Platinum EX */ + /* Win driver sets A_IOCFG output to 0x1c00 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]", .id = "Audigy2", @@ -1552,6 +1486,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .spdif_bug = 1, .invert_shared_spdif = 1, /* digital/analog switch swapped */ .ac97_chip = 1} , + /* Audigy 2 Platinum */ + /* Win driver sets A_IOCFG output to 0xa00 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", .id = "Audigy2", @@ -1657,6 +1593,9 @@ static const struct snd_emu_chip_details emu_chip_details[] = { .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , + /* SB Live! Platinum */ + /* Win driver sets A_IOCFG output to 0 */ + /* Tested by Jonathan Dowland <jon@dow.land> Apr 2023. */ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", .id = "Live", @@ -1901,11 +1840,12 @@ int snd_emu10k1_create(struct snd_card *card, pci_set_master(pci); - emu->fx8010.fxbus_mask = 0x303f; + // The masks are not used for Audigy. + // FIXME: these should come from the card_capabilites table. if (extin_mask == 0) - extin_mask = 0x3fcf; + extin_mask = 0x3fcf; // EXTIN_* if (extout_mask == 0) - extout_mask = 0x7fff; + extout_mask = 0x7fff; // EXTOUT_* emu->fx8010.extin_mask = extin_mask; emu->fx8010.extout_mask = extout_mask; emu->enable_ir = enable_ir; @@ -1970,12 +1910,10 @@ int snd_emu10k1_create(struct snd_card *card, pgtbl[idx] = cpu_to_le32(silent_page | idx); /* set up voice indices */ - for (idx = 0; idx < NUM_G; idx++) { - emu->voices[idx].emu = emu; + for (idx = 0; idx < NUM_G; idx++) emu->voices[idx].number = idx; - } - err = snd_emu10k1_init(emu, enable_ir, 0); + err = snd_emu10k1_init(emu, enable_ir); if (err < 0) return err; #ifdef CONFIG_PM_SLEEP @@ -2007,7 +1945,7 @@ static const unsigned char saved_regs[] = { 0xff /* end */ }; static const unsigned char saved_regs_audigy[] = { - A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE, + A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_EHC, A_FXRT2, A_SENDAMOUNTS, A_FXRT1, 0xff /* end */ }; @@ -2054,7 +1992,7 @@ void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu) *val = snd_emu10k1_ptr_read(emu, *reg, i); } if (emu->audigy) - emu->saved_a_iocfg = inl(emu->port + A_IOCFG); + emu->saved_a_iocfg = inw(emu->port + A_IOCFG); emu->saved_hcfg = inl(emu->port + HCFG); } @@ -2068,7 +2006,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) snd_emu10k1_emu1010_init(emu); else snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); - snd_emu10k1_init(emu, emu->enable_ir, 1); + snd_emu10k1_init(emu, emu->enable_ir); } void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) @@ -2081,7 +2019,7 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) /* resore for spdif */ if (emu->audigy) - outl(emu->saved_a_iocfg, emu->port + A_IOCFG); + outw(emu->saved_a_iocfg, emu->port + A_IOCFG); outl(emu->saved_hcfg, emu->port + HCFG); val = emu->saved_ptr; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 6cf7c8b1de47..db211a6e8a47 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -641,8 +641,8 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { kcontrol = ctl->kcontrol; if (kcontrol->id.iface == id->iface && - !strcmp(kcontrol->id.name, id->name) && - kcontrol->id.index == id->index) + kcontrol->id.index == id->index && + !strcmp(kcontrol->id.name, id->name)) return ctl; } return NULL; @@ -1187,8 +1187,8 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl } /* - * Used for emu1010 - conversion from 32-bit capture inputs from HANA - * to 2 x 16-bit registers in audigy - their values are read via DMA. + * Used for emu1010 - conversion from 32-bit capture inputs from the FPGA + * to 2 x 16-bit registers in Audigy - their values are read via DMA. * Conversion is performed by Audigy DSP instructions of FX8010. */ static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( @@ -1213,7 +1213,7 @@ static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) { - int err, i, z, gpr, nctl; + int err, z, gpr, nctl; int bit_shifter16; const int playback = 10; const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ @@ -1245,12 +1245,10 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) icode->code = icode->tram_addr_map + 256; /* clear free GPRs */ - for (i = 0; i < 512; i++) - set_bit(i, icode->gpr_valid); + memset(icode->gpr_valid, 0xff, 512 / 8); /* clear TRAM data & address lines */ - for (i = 0; i < 256; i++) - set_bit(i, icode->tram_valid); + memset(icode->tram_valid, 0xff, 256 / 8); strcpy(icode->name, "Audigy DSP code for ALSA"); ptr = 0; @@ -1261,9 +1259,6 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) gpr_map[gpr++] = 0x0000ffff; bit_shifter16 = gpr; - /* stop FX processor */ - snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); - #if 1 /* PCM front Playback Volume (independent from stereo mix) * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) @@ -1332,8 +1327,9 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) #define A_ADD_VOLUME_IN(var,vol,input) \ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) - /* emu1212 DSP 0 and DSP 1 Capture */ if (emu->card_capabilities->emu_model) { + /* EMU1010 DSP 0 and DSP 1 Capture */ + // The 24 MSB hold the actual value. We implicitly discard the 16 LSB. if (emu->card_capabilities->ca0108_chip) { /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); @@ -1638,8 +1634,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) #endif if (emu->card_capabilities->emu_model) { + /* Capture 16 channels of S32_LE sound. */ if (emu->card_capabilities->ca0108_chip) { dev_info(emu->card->dev, "EMU2 inputs on\n"); + /* Note that the Tina[2] DSPs have 16 more EMU32 inputs which we don't use. */ + for (z = 0; z < 0x10; z++) { snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, @@ -1648,7 +1647,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) } } else { dev_info(emu->card->dev, "EMU inputs on\n"); - /* Capture 16 (originally 8) channels of S32_LE sound */ + /* Note that the Alice2 DSPs have 6 I2S inputs which we don't use. */ /* dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n", @@ -1886,12 +1885,10 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) icode->code = icode->tram_addr_map + 160; /* clear free GPRs */ - for (i = 0; i < 256; i++) - set_bit(i, icode->gpr_valid); + memset(icode->gpr_valid, 0xff, 256 / 8); /* clear TRAM data & address lines */ - for (i = 0; i < 160; i++) - set_bit(i, icode->tram_valid); + memset(icode->tram_valid, 0xff, 160 / 8); strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); ptr = 0; i = 0; @@ -1903,9 +1900,6 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) tmp = 0x88; /* we need 4 temporary GPR */ /* from 0x8c to 0xff is the area for tone control */ - /* stop FX processor */ - snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP); - /* * Process FX Buses */ @@ -2523,7 +2517,7 @@ static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_info *info) { const char * const *fxbus, * const *extin, * const *extout; - unsigned short fxbus_mask, extin_mask, extout_mask; + unsigned short extin_mask, extout_mask; int res; info->internal_tram_size = emu->fx8010.itram_size; @@ -2531,11 +2525,10 @@ static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, fxbus = fxbuses; extin = emu->audigy ? audigy_ins : creative_ins; extout = emu->audigy ? audigy_outs : creative_outs; - fxbus_mask = emu->fx8010.fxbus_mask; - extin_mask = emu->fx8010.extin_mask; - extout_mask = emu->fx8010.extout_mask; + extin_mask = emu->audigy ? ~0 : emu->fx8010.extin_mask; + extout_mask = emu->audigy ? ~0 : emu->fx8010.extout_mask; for (res = 0; res < 16; res++, fxbus++, extin++, extout++) { - copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res); + copy_string(info->fxbus_names[res], *fxbus, "FXBUS", res); copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res); copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); } @@ -2651,17 +2644,19 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un return -EPERM; if (get_user(addr, (unsigned int __user *)argp)) return -EFAULT; - if (addr > 0x1ff) - return -EINVAL; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr); - udelay(10); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr); + if (emu->audigy) { + if (addr > A_DBG_STEP_ADDR) + return -EINVAL; + snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP); + udelay(10); + snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_STEP | addr); + } else { + if (addr > EMU10K1_DBG_SINGLE_STEP_ADDR) + return -EINVAL; + snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP); + udelay(10); + snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_STEP | addr); + } return 0; case SNDRV_EMU10K1_IOCTL_DBG_READ: if (emu->audigy) diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 3c115f8ab96c..8fce3413f4ae 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -346,7 +346,7 @@ static const unsigned int emu1616_output_dst[] = { }; /* - * Data destinations - HANA outputs going to Alice2 (audigy) for + * Data destinations - FPGA outputs going to Alice2 (Audigy) for * capture (EMU32 + I2S links) * Each destination has an enum mixer control to choose a data source */ @@ -367,6 +367,7 @@ static const unsigned int emu1010_input_dst[] = { EMU_DST_ALICE2_EMU32_D, EMU_DST_ALICE2_EMU32_E, EMU_DST_ALICE2_EMU32_F, + /* These exist only on rev1 EMU1010 cards. */ EMU_DST_ALICE_I2S0_LEFT, EMU_DST_ALICE_I2S0_RIGHT, EMU_DST_ALICE_I2S1_LEFT, @@ -708,7 +709,7 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, /* 44100 */ /* Mute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ + /* Default fallback clock 44.1kHz */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); /* Word Clock source, Internal 44.1kHz x1 */ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, @@ -924,7 +925,7 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int source_id; unsigned int ngain, ogain; - u32 gpio; + u16 gpio; int change = 0; unsigned long flags; u32 source; @@ -941,11 +942,11 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, if (change) { snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ spin_lock_irqsave(&emu->emu_lock, flags); - gpio = inl(emu->port + A_IOCFG); + gpio = inw(emu->port + A_IOCFG); if (source_id==0) - outl(gpio | 0x4, emu->port + A_IOCFG); + outw(gpio | 0x4, emu->port + A_IOCFG); else - outl(gpio & ~0x4, emu->port + A_IOCFG); + outw(gpio & ~0x4, emu->port + A_IOCFG); spin_unlock_irqrestore(&emu->emu_lock, flags); ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ @@ -1005,7 +1006,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int ogain; - unsigned int ngain; + unsigned int ngain0, ngain1; unsigned int source_id; int change = 0; @@ -1014,24 +1015,24 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, /* capture_source: uinfo->value.enumerated.items = 2 */ if (source_id >= 2) return -EINVAL; + ngain0 = ucontrol->value.integer.value[0]; + ngain1 = ucontrol->value.integer.value[1]; + if (ngain0 > 0xff) + return -EINVAL; + if (ngain1 > 0xff) + return -EINVAL; ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ngain = ucontrol->value.integer.value[0]; - if (ngain > 0xff) - return 0; - if (ogain != ngain) { + if (ogain != ngain0) { if (emu->i2c_capture_source == source_id) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); - emu->i2c_capture_volume[source_id][0] = ngain; + snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ngain0); + emu->i2c_capture_volume[source_id][0] = ngain0; change = 1; } ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ - ngain = ucontrol->value.integer.value[1]; - if (ngain > 0xff) - return 0; - if (ogain != ngain) { + if (ogain != ngain1) { if (emu->i2c_capture_source == source_id) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - emu->i2c_capture_volume[source_id][1] = ngain; + snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ngain1); + emu->i2c_capture_volume[source_id][1] = ngain1; change = 1; } @@ -1632,7 +1633,7 @@ static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); if (emu->audigy) - ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; + ucontrol->value.integer.value[0] = inw(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; else ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; if (emu->card_capabilities->invert_shared_spdif) @@ -1657,13 +1658,13 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, if ( emu->card_capabilities->i2c_adc) { /* Do nothing for Audigy 2 ZS Notebook */ } else if (emu->audigy) { - reg = inl(emu->port + A_IOCFG); + reg = inw(emu->port + A_IOCFG); val = sw ? A_IOCFG_GPOUT0 : 0; change = (reg & A_IOCFG_GPOUT0) != val; if (change) { reg &= ~A_IOCFG_GPOUT0; reg |= val; - outl(reg | val, emu->port + A_IOCFG); + outw(reg | val, emu->port + A_IOCFG); } } reg = inl(emu->port + HCFG); diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 6ec394fb1846..b0c0ef342756 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -76,23 +76,6 @@ static void snd_emu10k1_pcm_efx_interrupt(struct snd_emu10k1 *emu, snd_pcm_period_elapsed(emu->pcm_capture_efx_substream); } -static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; - ptr += runtime->buffer_size; - ptr -= epcm->ccca_start_addr; - ptr %= runtime->buffer_size; - - return ptr; -} - static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voices) { int err, i; @@ -343,7 +326,6 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, } else snd_emu10k1_ptr_write(emu, FXRT, voice, snd_emu10k1_compose_send_routing(send_routing)); - /* Stop CA */ /* Assumption that PT is already 0 so no harm overwriting */ snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); @@ -433,36 +415,6 @@ static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_emu10k1_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - if (epcm->extra) { - snd_emu10k1_voice_free(epcm->emu, epcm->extra); - epcm->extra = NULL; - } - if (epcm->voices[1]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); - epcm->voices[1] = NULL; - } - if (epcm->voices[0]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]); - epcm->voices[0] = NULL; - } - if (epcm->memblk) { - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = NULL; - epcm->start_addr = 0; - } - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; int i; if (runtime->private_data == NULL) @@ -527,9 +479,6 @@ static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream) start_addr = epcm->start_addr; end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); - /* - * the kX driver leaves some space between voices - */ channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK; snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, @@ -1091,8 +1040,6 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream) epcm->type = PLAYBACK_EFX; epcm->substream = substream; - emu->pcm_playback_efx_substream = substream; - runtime->private_data = epcm; runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_efx_playback; @@ -1267,9 +1214,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) runtime->hw.rate_min = runtime->hw.rate_max = 48000; spin_lock_irq(&emu->reg_lock); if (emu->card_capabilities->emu_model) { - /* Nb. of channels has been increased to 16 */ /* TODO - * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 @@ -1280,13 +1225,14 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) * Need to add mixer control to fix sample rate * * There are 32 mono channels of 16bits each. - * 24bit Audio uses 2x channels over 16bit - * 96kHz uses 2x channels over 48kHz - * 192kHz uses 4x channels over 48kHz - * So, for 48kHz 24bit, one has 16 channels - * for 96kHz 24bit, one has 8 channels - * for 192kHz 24bit, one has 4 channels - * + * 24bit Audio uses 2x channels over 16bit, + * 96kHz uses 2x channels over 48kHz, + * 192kHz uses 4x channels over 48kHz. + * So, for 48kHz 24bit, one has 16 channels, + * for 96kHz 24bit, one has 8 channels, + * for 192kHz 24bit, one has 4 channels. + * 1010rev2 and 1616(m) cards have double that, + * but we don't exceed 16 channels anyway. */ #if 1 switch (emu->emu1010.internal_clock) { @@ -1372,10 +1318,10 @@ static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { .open = snd_emu10k1_efx_playback_open, .close = snd_emu10k1_efx_playback_close, .hw_params = snd_emu10k1_playback_hw_params, - .hw_free = snd_emu10k1_efx_playback_hw_free, + .hw_free = snd_emu10k1_playback_hw_free, .prepare = snd_emu10k1_efx_playback_prepare, .trigger = snd_emu10k1_efx_playback_trigger, - .pointer = snd_emu10k1_efx_playback_pointer, + .pointer = snd_emu10k1_playback_pointer, }; int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device) @@ -1508,11 +1454,12 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, st nval[idx / 32] |= 1 << (idx % 32); bits++; } - + + // Check that the number of requested channels is a power of two + // not bigger than the number of available channels. for (idx = 0; idx < nefxb; idx++) if (1 << idx == bits) break; - if (idx >= nefxb) return -EINVAL; @@ -1802,7 +1749,6 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device) * to these */ - /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ if (emu->audigy) { emu->efx_voices_mask[0] = 0; if (emu->card_capabilities->emu_model) diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 6e20cca9c98f..bec72dc60a41 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -477,10 +477,7 @@ static void snd_emu_proc_ptr_reg_read(struct snd_info_entry *entry, for(i = offset; i < offset+length; i++) { snd_iprintf(buffer, "%02X: ",i); for (j = 0; j < voices; j++) { - if(iobase == 0) - value = snd_ptr_read(emu, 0, i, j); - else - value = snd_ptr_read(emu, 0x20, i, j); + value = snd_ptr_read(emu, iobase, i, j); snd_iprintf(buffer, "%08lX ", value); } snd_iprintf(buffer, "\n"); diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index e15092ce9848..c60573f14ea8 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -233,56 +233,57 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, return err; } -int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) +void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) { unsigned long flags; - if (reg > 0x3f) - return 1; + if (snd_BUG_ON(reg > 0x3f)) + return; reg += 0x40; /* 0x40 upwards are registers. */ - if (value > 0x3f) /* 0 to 0x3f are values */ - return 1; + if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */ + return; spin_lock_irqsave(&emu->emu_lock, flags); - outl(reg, emu->port + A_IOCFG); + outw(reg, emu->port + A_GPIO); udelay(10); - outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ + outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ udelay(10); - outl(value, emu->port + A_IOCFG); + outw(value, emu->port + A_GPIO); udelay(10); - outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ + outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ spin_unlock_irqrestore(&emu->emu_lock, flags); - - return 0; } -int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) +void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value) { + // The higest input pin is used as the designated interrupt trigger, + // so it needs to be masked out. + u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f; unsigned long flags; - if (reg > 0x3f) - return 1; + if (snd_BUG_ON(reg > 0x3f)) + return; reg += 0x40; /* 0x40 upwards are registers. */ spin_lock_irqsave(&emu->emu_lock, flags); - outl(reg, emu->port + A_IOCFG); + outw(reg, emu->port + A_GPIO); udelay(10); - outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ + outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ udelay(10); - *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f); + *value = ((inw(emu->port + A_GPIO) >> 8) & mask); spin_unlock_irqrestore(&emu->emu_lock, flags); - - return 0; } /* Each Destination has one and only one Source, * but one Source can feed any number of Destinations simultaneously. */ -int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src) +void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src) { - snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) ); - - return 0; + if (snd_BUG_ON(dst & ~0x71f)) + return; + if (snd_BUG_ON(src & ~0x71f)) + return; + snd_emu1010_fpga_write(emu, 0x00, dst >> 8); + snd_emu1010_fpga_write(emu, 0x01, dst & 0x1f); + snd_emu1010_fpga_write(emu, 0x02, src >> 8); + snd_emu1010_fpga_write(emu, 0x03, src & 0x1f); } void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) @@ -313,7 +314,6 @@ void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenu unsigned int val; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(CLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -333,7 +333,6 @@ void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicen unsigned int val; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(CLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -352,7 +351,6 @@ void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) unsigned long flags; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(CLIPH << 16, emu->port + PTR); voicenum = 1 << (voicenum - 32); @@ -370,7 +368,6 @@ void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned i unsigned int val; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(HLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -390,7 +387,6 @@ void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned unsigned int val; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(HLIEH << 16, emu->port + PTR); val = inl(emu->port + DATA); @@ -409,7 +405,6 @@ void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int unsigned long flags; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(HLIPH << 16, emu->port + PTR); voicenum = 1 << (voicenum - 32); @@ -427,7 +422,6 @@ void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voice unsigned int sol; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(SOLEH << 16, emu->port + PTR); sol = inl(emu->port + DATA); @@ -447,7 +441,6 @@ void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voi unsigned int sol; spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ if (voicenum >= 32) { outl(SOLEH << 16, emu->port + PTR); sol = inl(emu->port + DATA); diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index ebb2275efb6c..dfb44e5e69a7 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c @@ -18,7 +18,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) { struct snd_emu10k1 *emu = dev_id; - unsigned int status, status2, orig_status, orig_status2; + unsigned int status, orig_status; int handled = 0; int timeout = 0; @@ -139,32 +139,10 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) status &= ~IPR_FXDSP; } if (status & IPR_P16V) { - while ((status2 = inl(emu->port + IPR2)) != 0) { - u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ - struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]); - struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice); - - /* dev_dbg(emu->card->dev, "status2=0x%x\n", status2); */ - orig_status2 = status2; - if(status2 & mask) { - if(pvoice->use) { - snd_pcm_period_elapsed(pvoice->epcm->substream); - } else { - dev_err(emu->card->dev, - "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", - status2, mask, pvoice, - pvoice->use); - } - } - if(status2 & 0x110000) { - /* dev_info(emu->card->dev, "capture int found\n"); */ - if(cvoice->use) { - /* dev_info(emu->card->dev, "capture period_elapsed\n"); */ - snd_pcm_period_elapsed(cvoice->epcm->substream); - } - } - outl(orig_status2, emu->port + IPR2); /* ack all */ - } + if (emu->p16v_interrupt) + emu->p16v_interrupt(emu); + else + outl(0, emu->port + INTE2); status &= ~IPR_P16V; } diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 18a1b0740e6b..ce4d3450959c 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -149,42 +149,19 @@ static const struct snd_pcm_hardware snd_p16v_capture_hw = { .fifo_size = 0, }; -static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - struct snd_emu10k1_pcm *epcm = runtime->private_data; - - kfree(epcm); -} - /* open_playback callback */ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) { - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]); - struct snd_emu10k1_pcm *epcm; struct snd_pcm_runtime *runtime = substream->runtime; int err; - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */ - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; /* dev_dbg(emu->card->dev, "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_playback_hw; - channel->emu = emu; - channel->number = channel_id; - - channel->use=1; #if 0 /* debug */ dev_dbg(emu->card->dev, "p16v: open channel_id=%d, channel=%p, use=0x%x\n", @@ -193,7 +170,6 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea channel_id, chip, channel); #endif /* debug */ /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ - channel->epcm = epcm; err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) return err; @@ -205,44 +181,20 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea return 0; } + /* open_capture callback */ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id) { - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice); - struct snd_emu10k1_pcm *epcm; struct snd_pcm_runtime *runtime = substream->runtime; int err; - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */ - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; /* dev_dbg(emu->card->dev, "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; -#if 0 /* debug */ - dev_dbg(emu->card->dev, - "p16v: open channel_id=%d, channel=%p, use=0x%x\n", - channel_id, channel, channel->use); - dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); -#endif /* debug */ - /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ - channel->epcm = epcm; err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) return err; @@ -254,22 +206,12 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream /* close callback */ static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream) { - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - //struct snd_pcm_runtime *runtime = substream->runtime; - //struct snd_emu10k1_pcm *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(struct snd_pcm_substream *substream) { - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - //struct snd_pcm_runtime *runtime = substream->runtime; - //struct snd_emu10k1_pcm *epcm = runtime->private_data; - emu->p16v_capture_voice.use = 0; - /* FIXME: maybe zero others */ return 0; } @@ -411,13 +353,48 @@ static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) spin_unlock_irqrestore(&emu->emu_lock, flags); } +static void snd_p16v_interrupt(struct snd_emu10k1 *emu) +{ + unsigned int status; + + while ((status = inl(emu->port + IPR2)) != 0) { + u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ + + /* dev_dbg(emu->card->dev, "p16v status=0x%x\n", status); */ + if (status & mask) { + struct snd_pcm_substream *substream = + emu->pcm_p16v->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct snd_pcm_runtime *runtime = substream->runtime; + + if (runtime && runtime->private_data) { + snd_pcm_period_elapsed(substream); + } else { + dev_err(emu->card->dev, + "p16v: status: 0x%08x, mask=0x%08x\n", + status, mask); + } + } + if (status & 0x110000) { + struct snd_pcm_substream *substream = + emu->pcm_p16v->streams[SNDRV_PCM_STREAM_CAPTURE].substream; + struct snd_pcm_runtime *runtime = substream->runtime; + + /* dev_info(emu->card->dev, "capture int found\n"); */ + if (runtime && runtime->private_data) { + /* dev_info(emu->card->dev, "capture period_elapsed\n"); */ + snd_pcm_period_elapsed(substream); + } + } + outl(status, emu->port + IPR2); /* ack all */ + } +} + /* trigger_playback callback */ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, int cmd) { struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime; - struct snd_emu10k1_pcm *epcm; int channel; int result = 0; struct snd_pcm_substream *s; @@ -439,10 +416,9 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, s->stream != SNDRV_PCM_STREAM_PLAYBACK) continue; runtime = s->runtime; - epcm = runtime->private_data; channel = substream->pcm->device-emu->p16v_device_offset; /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */ - epcm->running = running; + runtime->private_data = (void *)(ptrdiff_t)running; basic |= (0x1<<channel); inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); snd_pcm_trigger_done(s, substream); @@ -471,7 +447,6 @@ static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream, { struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; int channel = 0; int result = 0; u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; @@ -480,13 +455,13 @@ static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream, 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<<channel)); - epcm->running = 1; + runtime->private_data = (void *)1; break; case SNDRV_PCM_TRIGGER_STOP: snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel)); snd_p16v_intr_disable(emu, inte); //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel)); - epcm->running = 0; + runtime->private_data = NULL; break; default: result = -EINVAL; @@ -501,10 +476,10 @@ snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream) { struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; int channel = substream->pcm->device - emu->p16v_device_offset; - if (!epcm->running) + + if (!runtime->private_data) return 0; ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); @@ -526,11 +501,10 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) { struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; int channel = 0; - if (!epcm->running) + if (!runtime->private_data) return 0; ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); @@ -591,6 +565,7 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device) pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; strcpy(pcm->name, "p16v"); emu->pcm_p16v = pcm; + emu->p16v_interrupt = snd_p16v_interrupt; for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; diff --git a/sound/pci/emu10k1/p16v.h b/sound/pci/emu10k1/p16v.h index 3cdafa311617..9d429ad1feff 100644 --- a/sound/pci/emu10k1/p16v.h +++ b/sound/pci/emu10k1/p16v.h @@ -64,7 +64,7 @@ */ /********************************************************************************************************/ -/* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */ +/* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */ /********************************************************************************************************/ /* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE. diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h index 3a6568346fad..d4ada1c430c8 100644 --- a/sound/pci/emu10k1/p17v.h +++ b/sound/pci/emu10k1/p17v.h @@ -6,8 +6,8 @@ */ /******************************************************************************/ -/* Audigy2Value Tina (P17V) pointer-offset register set, - * accessed through the PTR20 and DATA24 registers */ +/* Audigy2Value Tina (P17V) pointer-offset register set, */ +/* accessed through the PTR2 and DATA2 registers */ /******************************************************************************/ /* 00 - 07: Not used */ diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 75020edd39e7..b5210abb5141 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -514,13 +514,13 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) break; case HDA_GEN_PCM_ACT_PREPARE: mutex_lock(&cs35l41->fw_mutex); - ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1, NULL); mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLEANUP: mutex_lock(&cs35l41->fw_mutex); regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); - ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0, NULL); mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLOSE: @@ -672,7 +672,7 @@ static int cs35l41_runtime_suspend(struct device *dev) if (cs35l41->playback_started) { regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); - cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, NULL); regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 77a592f21947..881b2f3a1551 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2528,6 +2528,9 @@ static const struct pci_device_id azx_ids[] = { /* Meteorlake-P */ { PCI_DEVICE(0x8086, 0x7e28), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Lunarlake-P */ + { PCI_DEVICE(0x8086, 0xa828), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index c2bf86781894..9d0ab043880b 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -580,12 +580,10 @@ static void hda_tegra_probe_work(struct work_struct *work) return; /* no error return from async probe */ } -static int hda_tegra_remove(struct platform_device *pdev) +static void hda_tegra_remove(struct platform_device *pdev) { snd_card_free(dev_get_drvdata(&pdev->dev)); pm_runtime_disable(&pdev->dev); - - return 0; } static void hda_tegra_shutdown(struct platform_device *pdev) @@ -607,7 +605,7 @@ static struct platform_driver tegra_platform_hda = { .of_match_table = hda_tegra_match, }, .probe = hda_tegra_probe, - .remove = hda_tegra_remove, + .remove_new = hda_tegra_remove, .shutdown = hda_tegra_shutdown, }; module_platform_driver(tegra_platform_hda); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5c6980394dce..ee051bdfaff6 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2104,10 +2104,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, goto unlock; } - if (snd_BUG_ON(pin_idx < 0)) { - err = -EINVAL; - goto unlock; - } per_pin = get_pin(spec, pin_idx); /* Verify pin:cvt selections to avoid silent audio after S3. @@ -2199,13 +2195,13 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); + /* + * In such a case, return 0 to match the behavior in + * hdmi_pcm_open() + */ if (pin_idx < 0) goto unlock; - if (snd_BUG_ON(pin_idx < 0)) { - err = -EINVAL; - goto unlock; - } per_pin = get_pin(spec, pin_idx); if (spec->dyn_pin_out) { diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index fa1812e7a49d..267c7848974a 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6146,12 +6146,6 @@ static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) return 0; } -static inline int copy_u32_le(void __user *dest, void __iomem *src) -{ - u32 val = readl(src); - return copy_to_user(dest, &val, 4); -} - static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) { diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 82d4e0fda91b..b033bd290940 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -98,8 +98,10 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, case 0x204: legacy_ctrl2 |= 2 << 6; break; case 0x205: legacy_ctrl2 |= 3 << 6; break; default: - dev_err(chip->card->dev, - "invalid joystick port %#x", io_port); + if (io_port > 0) + dev_err(chip->card->dev, + "The %s does not support arbitrary IO ports for the game port (requested 0x%x)\n", + chip->card->shortname, (unsigned int)io_port); return -EINVAL; } } @@ -186,6 +188,13 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, default: model = str = "???"; break; } + strcpy(card->driver, str); + sprintf(card->shortname, "Yamaha %s (%s)", model, str); + sprintf(card->longname, "%s at 0x%lx, irq %i", + card->shortname, + chip->reg_area_phys, + chip->irq); + legacy_ctrl = 0; legacy_ctrl2 = 0x0800; /* SBEN = 0, SMOD = 01, LAD = 0 */ @@ -218,7 +227,13 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, case 0x398: legacy_ctrl2 |= 1; break; case 0x3a0: legacy_ctrl2 |= 2; break; case 0x3a8: legacy_ctrl2 |= 3; break; - default: fm_port[dev] = 0; break; + default: + if (fm_port[dev] > 0) + dev_err(card->dev, + "The %s does not support arbitrary IO ports for FM (requested 0x%x)\n", + card->shortname, (unsigned int)fm_port[dev]); + fm_port[dev] = 0; + break; } if (fm_port[dev] > 0) fm_res = devm_request_region(&pci->dev, fm_port[dev], @@ -234,7 +249,13 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, case 0x300: legacy_ctrl2 |= 1 << 4; break; case 0x332: legacy_ctrl2 |= 2 << 4; break; case 0x334: legacy_ctrl2 |= 3 << 4; break; - default: mpu_port[dev] = 0; break; + default: + if (mpu_port[dev] > 0) + dev_err(card->dev, + "The %s does not support arbitrary IO ports for MPU-401 (requested 0x%x)\n", + card->shortname, (unsigned int)mpu_port[dev]); + mpu_port[dev] = 0; + break; } if (mpu_port[dev] > 0) mpu_res = devm_request_region(&pci->dev, mpu_port[dev], @@ -257,12 +278,6 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, if (err < 0) return err; - strcpy(card->driver, str); - sprintf(card->shortname, "Yamaha %s (%s)", model, str); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, - chip->reg_area_phys, - chip->irq); err = snd_ymfpci_pcm(chip, 0); if (err < 0) return err; @@ -337,11 +352,9 @@ static struct pci_driver ymfpci_driver = { .name = KBUILD_MODNAME, .id_table = snd_ymfpci_ids, .probe = snd_card_ymfpci_probe, -#ifdef CONFIG_PM_SLEEP .driver = { - .pm = &snd_ymfpci_pm, + .pm = pm_sleep_ptr(&snd_ymfpci_pm), }, -#endif }; module_pci_driver(ymfpci_driver); diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h index 66968776478a..a408785cfa1b 100644 --- a/sound/pci/ymfpci/ymfpci.h +++ b/sound/pci/ymfpci/ymfpci.h @@ -268,6 +268,49 @@ struct snd_ymfpci_pcm { u32 shift; }; +static const int saved_regs_index[] = { + /* spdif */ + YDSXGR_SPDIFOUTCTRL, + YDSXGR_SPDIFOUTSTATUS, + YDSXGR_SPDIFINCTRL, + /* volumes */ + YDSXGR_PRIADCLOOPVOL, + YDSXGR_NATIVEDACINVOL, + YDSXGR_NATIVEDACOUTVOL, + YDSXGR_BUF441OUTVOL, + YDSXGR_NATIVEADCINVOL, + YDSXGR_SPDIFLOOPVOL, + YDSXGR_SPDIFOUTVOL, + YDSXGR_ZVOUTVOL, + YDSXGR_LEGACYOUTVOL, + /* address bases */ + YDSXGR_PLAYCTRLBASE, + YDSXGR_RECCTRLBASE, + YDSXGR_EFFCTRLBASE, + YDSXGR_WORKBASE, + /* capture set up */ + YDSXGR_MAPOFREC, + YDSXGR_RECFORMAT, + YDSXGR_RECSLOTSR, + YDSXGR_ADCFORMAT, + YDSXGR_ADCSLOTSR, +}; +#define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) + +static const int pci_saved_regs_index[] = { + /* All Chips */ + PCIR_DSXG_LEGACY, + PCIR_DSXG_ELEGACY, + /* YMF 744/754 */ + PCIR_DSXG_FMBASE, + PCIR_DSXG_SBBASE, + PCIR_DSXG_MPU401BASE, + PCIR_DSXG_JOYBASE, +}; +#define DSXG_PCI_NUM_SAVED_REGS ARRAY_SIZE(pci_saved_regs_index) +#define DSXG_PCI_NUM_SAVED_LEGACY_REGS 2 +static_assert(DSXG_PCI_NUM_SAVED_LEGACY_REGS <= DSXG_PCI_NUM_SAVED_REGS); + struct snd_ymfpci { int irq; @@ -276,7 +319,7 @@ struct snd_ymfpci { unsigned long reg_area_phys; void __iomem *reg_area_virt; - unsigned short old_legacy_ctrl; + u16 old_legacy_ctrl; #ifdef SUPPORT_JOYSTICK struct gameport *gameport; #endif @@ -345,17 +388,14 @@ struct snd_ymfpci { const struct firmware *dsp_microcode; const struct firmware *controller_microcode; -#ifdef CONFIG_PM_SLEEP - u32 *saved_regs; + u32 saved_regs[YDSXGR_NUM_SAVED_REGS]; u32 saved_ydsxgr_mode; - u16 saved_dsxg_legacy; - u16 saved_dsxg_elegacy; -#endif + u16 saved_dsxg_pci_regs[DSXG_PCI_NUM_SAVED_REGS]; }; int snd_ymfpci_create(struct snd_card *card, struct pci_dev *pci, - unsigned short old_legacy_ctrl); + u16 old_legacy_ctrl); void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); extern const struct dev_pm_ops snd_ymfpci_pm; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index b492c32ce070..6971eec45a4d 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -31,11 +31,6 @@ static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip); -static inline u8 snd_ymfpci_readb(struct snd_ymfpci *chip, u32 offset) -{ - return readb(chip->reg_area_virt + offset); -} - static inline void snd_ymfpci_writeb(struct snd_ymfpci *chip, u32 offset, u8 val) { writeb(val, chip->reg_area_virt + offset); @@ -2219,57 +2214,33 @@ static void snd_ymfpci_free(struct snd_card *card) snd_ymfpci_free_gameport(chip); - pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); + pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, chip->old_legacy_ctrl); release_firmware(chip->dsp_microcode); release_firmware(chip->controller_microcode); } -#ifdef CONFIG_PM_SLEEP -static const int saved_regs_index[] = { - /* spdif */ - YDSXGR_SPDIFOUTCTRL, - YDSXGR_SPDIFOUTSTATUS, - YDSXGR_SPDIFINCTRL, - /* volumes */ - YDSXGR_PRIADCLOOPVOL, - YDSXGR_NATIVEDACINVOL, - YDSXGR_NATIVEDACOUTVOL, - YDSXGR_BUF441OUTVOL, - YDSXGR_NATIVEADCINVOL, - YDSXGR_SPDIFLOOPVOL, - YDSXGR_SPDIFOUTVOL, - YDSXGR_ZVOUTVOL, - YDSXGR_LEGACYOUTVOL, - /* address bases */ - YDSXGR_PLAYCTRLBASE, - YDSXGR_RECCTRLBASE, - YDSXGR_EFFCTRLBASE, - YDSXGR_WORKBASE, - /* capture set up */ - YDSXGR_MAPOFREC, - YDSXGR_RECFORMAT, - YDSXGR_RECSLOTSR, - YDSXGR_ADCFORMAT, - YDSXGR_ADCSLOTSR, -}; -#define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) - static int snd_ymfpci_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct snd_ymfpci *chip = card->private_data; - unsigned int i; - + unsigned int i, legacy_reg_count = DSXG_PCI_NUM_SAVED_LEGACY_REGS; + + if (chip->pci->device >= 0x0010) /* YMF 744/754 */ + legacy_reg_count = DSXG_PCI_NUM_SAVED_REGS; + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_ac97_suspend(chip->ac97); + for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); + chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); - pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, - &chip->saved_dsxg_legacy); - pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY, - &chip->saved_dsxg_elegacy); + + for (i = 0; i < legacy_reg_count; i++) + pci_read_config_word(chip->pci, pci_saved_regs_index[i], + chip->saved_dsxg_pci_regs + i); + snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); snd_ymfpci_disable_dsp(chip); @@ -2281,7 +2252,10 @@ static int snd_ymfpci_resume(struct device *dev) struct pci_dev *pci = to_pci_dev(dev); struct snd_card *card = dev_get_drvdata(dev); struct snd_ymfpci *chip = card->private_data; - unsigned int i; + unsigned int i, legacy_reg_count = DSXG_PCI_NUM_SAVED_LEGACY_REGS; + + if (chip->pci->device >= 0x0010) /* YMF 744/754 */ + legacy_reg_count = DSXG_PCI_NUM_SAVED_REGS; snd_ymfpci_aclink_reset(pci); snd_ymfpci_codec_ready(chip, 0); @@ -2293,10 +2267,9 @@ static int snd_ymfpci_resume(struct device *dev) snd_ac97_resume(chip->ac97); - pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, - chip->saved_dsxg_legacy); - pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, - chip->saved_dsxg_elegacy); + for (i = 0; i < legacy_reg_count; i++) + pci_write_config_word(chip->pci, pci_saved_regs_index[i], + chip->saved_dsxg_pci_regs[i]); /* start hw again */ if (chip->start_count > 0) { @@ -2309,12 +2282,11 @@ static int snd_ymfpci_resume(struct device *dev) return 0; } -SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); -#endif /* CONFIG_PM_SLEEP */ +DEFINE_SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); int snd_ymfpci_create(struct snd_card *card, struct pci_dev *pci, - unsigned short old_legacy_ctrl) + u16 old_legacy_ctrl) { struct snd_ymfpci *chip = card->private_data; int err; @@ -2379,13 +2351,6 @@ int snd_ymfpci_create(struct snd_card *card, if (err < 0) return err; -#ifdef CONFIG_PM_SLEEP - chip->saved_regs = devm_kmalloc_array(&pci->dev, YDSXGR_NUM_SAVED_REGS, - sizeof(u32), GFP_KERNEL); - if (!chip->saved_regs) - return -ENOMEM; -#endif - snd_ymfpci_proc_init(card, chip); return 0; |