diff options
Diffstat (limited to '')
-rw-r--r-- | sound/pci/ymfpci/ymfpci.h | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h new file mode 100644 index 0000000000..a408785cfa --- /dev/null +++ b/sound/pci/ymfpci/ymfpci.h @@ -0,0 +1,410 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __SOUND_YMFPCI_H +#define __SOUND_YMFPCI_H + +/* + * Copyright (c) by Jaroslav Kysela <perex@perex.cz> + * Definitions for Yahama YMF724/740/744/754 chips + */ + +#include <sound/pcm.h> +#include <sound/rawmidi.h> +#include <sound/ac97_codec.h> +#include <sound/timer.h> +#include <linux/gameport.h> + +/* + * Direct registers + */ + +#define YMFREG(chip, reg) (chip->port + YDSXGR_##reg) + +#define YDSXGR_INTFLAG 0x0004 +#define YDSXGR_ACTIVITY 0x0006 +#define YDSXGR_GLOBALCTRL 0x0008 +#define YDSXGR_ZVCTRL 0x000A +#define YDSXGR_TIMERCTRL 0x0010 +#define YDSXGR_TIMERCOUNT 0x0012 +#define YDSXGR_SPDIFOUTCTRL 0x0018 +#define YDSXGR_SPDIFOUTSTATUS 0x001C +#define YDSXGR_EEPROMCTRL 0x0020 +#define YDSXGR_SPDIFINCTRL 0x0034 +#define YDSXGR_SPDIFINSTATUS 0x0038 +#define YDSXGR_DSPPROGRAMDL 0x0048 +#define YDSXGR_DLCNTRL 0x004C +#define YDSXGR_GPIOININTFLAG 0x0050 +#define YDSXGR_GPIOININTENABLE 0x0052 +#define YDSXGR_GPIOINSTATUS 0x0054 +#define YDSXGR_GPIOOUTCTRL 0x0056 +#define YDSXGR_GPIOFUNCENABLE 0x0058 +#define YDSXGR_GPIOTYPECONFIG 0x005A +#define YDSXGR_AC97CMDDATA 0x0060 +#define YDSXGR_AC97CMDADR 0x0062 +#define YDSXGR_PRISTATUSDATA 0x0064 +#define YDSXGR_PRISTATUSADR 0x0066 +#define YDSXGR_SECSTATUSDATA 0x0068 +#define YDSXGR_SECSTATUSADR 0x006A +#define YDSXGR_SECCONFIG 0x0070 +#define YDSXGR_LEGACYOUTVOL 0x0080 +#define YDSXGR_LEGACYOUTVOLL 0x0080 +#define YDSXGR_LEGACYOUTVOLR 0x0082 +#define YDSXGR_NATIVEDACOUTVOL 0x0084 +#define YDSXGR_NATIVEDACOUTVOLL 0x0084 +#define YDSXGR_NATIVEDACOUTVOLR 0x0086 +#define YDSXGR_ZVOUTVOL 0x0088 +#define YDSXGR_ZVOUTVOLL 0x0088 +#define YDSXGR_ZVOUTVOLR 0x008A +#define YDSXGR_SECADCOUTVOL 0x008C +#define YDSXGR_SECADCOUTVOLL 0x008C +#define YDSXGR_SECADCOUTVOLR 0x008E +#define YDSXGR_PRIADCOUTVOL 0x0090 +#define YDSXGR_PRIADCOUTVOLL 0x0090 +#define YDSXGR_PRIADCOUTVOLR 0x0092 +#define YDSXGR_LEGACYLOOPVOL 0x0094 +#define YDSXGR_LEGACYLOOPVOLL 0x0094 +#define YDSXGR_LEGACYLOOPVOLR 0x0096 +#define YDSXGR_NATIVEDACLOOPVOL 0x0098 +#define YDSXGR_NATIVEDACLOOPVOLL 0x0098 +#define YDSXGR_NATIVEDACLOOPVOLR 0x009A +#define YDSXGR_ZVLOOPVOL 0x009C +#define YDSXGR_ZVLOOPVOLL 0x009E +#define YDSXGR_ZVLOOPVOLR 0x009E +#define YDSXGR_SECADCLOOPVOL 0x00A0 +#define YDSXGR_SECADCLOOPVOLL 0x00A0 +#define YDSXGR_SECADCLOOPVOLR 0x00A2 +#define YDSXGR_PRIADCLOOPVOL 0x00A4 +#define YDSXGR_PRIADCLOOPVOLL 0x00A4 +#define YDSXGR_PRIADCLOOPVOLR 0x00A6 +#define YDSXGR_NATIVEADCINVOL 0x00A8 +#define YDSXGR_NATIVEADCINVOLL 0x00A8 +#define YDSXGR_NATIVEADCINVOLR 0x00AA +#define YDSXGR_NATIVEDACINVOL 0x00AC +#define YDSXGR_NATIVEDACINVOLL 0x00AC +#define YDSXGR_NATIVEDACINVOLR 0x00AE +#define YDSXGR_BUF441OUTVOL 0x00B0 +#define YDSXGR_BUF441OUTVOLL 0x00B0 +#define YDSXGR_BUF441OUTVOLR 0x00B2 +#define YDSXGR_BUF441LOOPVOL 0x00B4 +#define YDSXGR_BUF441LOOPVOLL 0x00B4 +#define YDSXGR_BUF441LOOPVOLR 0x00B6 +#define YDSXGR_SPDIFOUTVOL 0x00B8 +#define YDSXGR_SPDIFOUTVOLL 0x00B8 +#define YDSXGR_SPDIFOUTVOLR 0x00BA +#define YDSXGR_SPDIFLOOPVOL 0x00BC +#define YDSXGR_SPDIFLOOPVOLL 0x00BC +#define YDSXGR_SPDIFLOOPVOLR 0x00BE +#define YDSXGR_ADCSLOTSR 0x00C0 +#define YDSXGR_RECSLOTSR 0x00C4 +#define YDSXGR_ADCFORMAT 0x00C8 +#define YDSXGR_RECFORMAT 0x00CC +#define YDSXGR_P44SLOTSR 0x00D0 +#define YDSXGR_STATUS 0x0100 +#define YDSXGR_CTRLSELECT 0x0104 +#define YDSXGR_MODE 0x0108 +#define YDSXGR_SAMPLECOUNT 0x010C +#define YDSXGR_NUMOFSAMPLES 0x0110 +#define YDSXGR_CONFIG 0x0114 +#define YDSXGR_PLAYCTRLSIZE 0x0140 +#define YDSXGR_RECCTRLSIZE 0x0144 +#define YDSXGR_EFFCTRLSIZE 0x0148 +#define YDSXGR_WORKSIZE 0x014C +#define YDSXGR_MAPOFREC 0x0150 +#define YDSXGR_MAPOFEFFECT 0x0154 +#define YDSXGR_PLAYCTRLBASE 0x0158 +#define YDSXGR_RECCTRLBASE 0x015C +#define YDSXGR_EFFCTRLBASE 0x0160 +#define YDSXGR_WORKBASE 0x0164 +#define YDSXGR_DSPINSTRAM 0x1000 +#define YDSXGR_CTRLINSTRAM 0x4000 + +#define YDSXG_AC97READCMD 0x8000 +#define YDSXG_AC97WRITECMD 0x0000 + +#define PCIR_DSXG_LEGACY 0x40 +#define PCIR_DSXG_ELEGACY 0x42 +#define PCIR_DSXG_CTRL 0x48 +#define PCIR_DSXG_PWRCTRL1 0x4a +#define PCIR_DSXG_PWRCTRL2 0x4e +#define PCIR_DSXG_FMBASE 0x60 +#define PCIR_DSXG_SBBASE 0x62 +#define PCIR_DSXG_MPU401BASE 0x64 +#define PCIR_DSXG_JOYBASE 0x66 + +#define YDSXG_DSPLENGTH 0x0080 +#define YDSXG_CTRLLENGTH 0x3000 + +#define YDSXG_DEFAULT_WORK_SIZE 0x0400 + +#define YDSXG_PLAYBACK_VOICES 64 +#define YDSXG_CAPTURE_VOICES 2 +#define YDSXG_EFFECT_VOICES 5 + +#define YMFPCI_LEGACY_SBEN (1 << 0) /* soundblaster enable */ +#define YMFPCI_LEGACY_FMEN (1 << 1) /* OPL3 enable */ +#define YMFPCI_LEGACY_JPEN (1 << 2) /* joystick enable */ +#define YMFPCI_LEGACY_MEN (1 << 3) /* MPU401 enable */ +#define YMFPCI_LEGACY_MIEN (1 << 4) /* MPU RX irq enable */ +#define YMFPCI_LEGACY_IOBITS (1 << 5) /* i/o bits range, 0 = 16bit, 1 =10bit */ +#define YMFPCI_LEGACY_SDMA (3 << 6) /* SB DMA select */ +#define YMFPCI_LEGACY_SBIRQ (7 << 8) /* SB IRQ select */ +#define YMFPCI_LEGACY_MPUIRQ (7 << 11) /* MPU IRQ select */ +#define YMFPCI_LEGACY_SIEN (1 << 14) /* serialized IRQ */ +#define YMFPCI_LEGACY_LAD (1 << 15) /* legacy audio disable */ + +#define YMFPCI_LEGACY2_FMIO (3 << 0) /* OPL3 i/o address (724/740) */ +#define YMFPCI_LEGACY2_SBIO (3 << 2) /* SB i/o address (724/740) */ +#define YMFPCI_LEGACY2_MPUIO (3 << 4) /* MPU401 i/o address (724/740) */ +#define YMFPCI_LEGACY2_JSIO (3 << 6) /* joystick i/o address (724/740) */ +#define YMFPCI_LEGACY2_MAIM (1 << 8) /* MPU401 ack intr mask */ +#define YMFPCI_LEGACY2_SMOD (3 << 11) /* SB DMA mode */ +#define YMFPCI_LEGACY2_SBVER (3 << 13) /* SB version select */ +#define YMFPCI_LEGACY2_IMOD (1 << 15) /* legacy IRQ mode */ +/* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */ + +#if IS_REACHABLE(CONFIG_GAMEPORT) +#define SUPPORT_JOYSTICK +#endif + +/* + * + */ + +struct snd_ymfpci_playback_bank { + __le32 format; + __le32 loop_default; + __le32 base; /* 32-bit address */ + __le32 loop_start; /* 32-bit offset */ + __le32 loop_end; /* 32-bit offset */ + __le32 loop_frac; /* 8-bit fraction - loop_start */ + __le32 delta_end; /* pitch delta end */ + __le32 lpfK_end; + __le32 eg_gain_end; + __le32 left_gain_end; + __le32 right_gain_end; + __le32 eff1_gain_end; + __le32 eff2_gain_end; + __le32 eff3_gain_end; + __le32 lpfQ; + __le32 status; + __le32 num_of_frames; + __le32 loop_count; + __le32 start; + __le32 start_frac; + __le32 delta; + __le32 lpfK; + __le32 eg_gain; + __le32 left_gain; + __le32 right_gain; + __le32 eff1_gain; + __le32 eff2_gain; + __le32 eff3_gain; + __le32 lpfD1; + __le32 lpfD2; + }; + +struct snd_ymfpci_capture_bank { + __le32 base; /* 32-bit address */ + __le32 loop_end; /* 32-bit offset */ + __le32 start; /* 32-bit offset */ + __le32 num_of_loops; /* counter */ +}; + +struct snd_ymfpci_effect_bank { + __le32 base; /* 32-bit address */ + __le32 loop_end; /* 32-bit offset */ + __le32 start; /* 32-bit offset */ + __le32 temp; +}; + +struct snd_ymfpci_pcm; +struct snd_ymfpci; + +enum snd_ymfpci_voice_type { + YMFPCI_PCM, + YMFPCI_SYNTH, + YMFPCI_MIDI +}; + +struct snd_ymfpci_voice { + struct snd_ymfpci *chip; + int number; + unsigned int use: 1, + pcm: 1, + synth: 1, + midi: 1; + struct snd_ymfpci_playback_bank *bank; + dma_addr_t bank_addr; + void (*interrupt)(struct snd_ymfpci *chip, struct snd_ymfpci_voice *voice); + struct snd_ymfpci_pcm *ypcm; +}; + +enum snd_ymfpci_pcm_type { + PLAYBACK_VOICE, + CAPTURE_REC, + CAPTURE_AC97, + EFFECT_DRY_LEFT, + EFFECT_DRY_RIGHT, + EFFECT_EFF1, + EFFECT_EFF2, + EFFECT_EFF3 +}; + +struct snd_ymfpci_pcm { + struct snd_ymfpci *chip; + enum snd_ymfpci_pcm_type type; + struct snd_pcm_substream *substream; + struct snd_ymfpci_voice *voices[2]; /* playback only */ + unsigned int running: 1, + use_441_slot: 1, + output_front: 1, + output_rear: 1, + swap_rear: 1; + unsigned int update_pcm_vol; + u32 period_size; /* cached from runtime->period_size */ + u32 buffer_size; /* cached from runtime->buffer_size */ + u32 period_pos; + u32 last_pos; + u32 capture_bank_number; + 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; + + unsigned int device_id; /* PCI device ID */ + unsigned char rev; /* PCI revision */ + unsigned long reg_area_phys; + void __iomem *reg_area_virt; + + u16 old_legacy_ctrl; +#ifdef SUPPORT_JOYSTICK + struct gameport *gameport; +#endif + + struct snd_dma_buffer *work_ptr; + + unsigned int bank_size_playback; + unsigned int bank_size_capture; + unsigned int bank_size_effect; + unsigned int work_size; + + void *bank_base_playback; + void *bank_base_capture; + void *bank_base_effect; + void *work_base; + dma_addr_t bank_base_playback_addr; + dma_addr_t bank_base_capture_addr; + dma_addr_t bank_base_effect_addr; + dma_addr_t work_base_addr; + struct snd_dma_buffer ac3_tmp_base; + + __le32 *ctrl_playback; + struct snd_ymfpci_playback_bank *bank_playback[YDSXG_PLAYBACK_VOICES][2]; + struct snd_ymfpci_capture_bank *bank_capture[YDSXG_CAPTURE_VOICES][2]; + struct snd_ymfpci_effect_bank *bank_effect[YDSXG_EFFECT_VOICES][2]; + + int start_count; + + u32 active_bank; + struct snd_ymfpci_voice voices[64]; + int src441_used; + + struct snd_ac97_bus *ac97_bus; + struct snd_ac97 *ac97; + struct snd_rawmidi *rawmidi; + struct snd_timer *timer; + unsigned int timer_ticks; + + struct pci_dev *pci; + struct snd_card *card; + struct snd_pcm *pcm; + struct snd_pcm *pcm2; + struct snd_pcm *pcm_spdif; + struct snd_pcm *pcm_4ch; + struct snd_pcm_substream *capture_substream[YDSXG_CAPTURE_VOICES]; + struct snd_pcm_substream *effect_substream[YDSXG_EFFECT_VOICES]; + struct snd_kcontrol *ctl_vol_recsrc; + struct snd_kcontrol *ctl_vol_adcrec; + struct snd_kcontrol *ctl_vol_spdifrec; + unsigned short spdif_bits, spdif_pcm_bits; + struct snd_kcontrol *spdif_pcm_ctl; + int mode_dup4ch; + int rear_opened; + int spdif_opened; + struct snd_ymfpci_pcm_mixer { + u16 left; + u16 right; + struct snd_kcontrol *ctl; + } pcm_mixer[32]; + + spinlock_t reg_lock; + spinlock_t voice_lock; + wait_queue_head_t interrupt_sleep; + atomic_t interrupt_sleep_count; + struct snd_info_entry *proc_entry; + const struct firmware *dsp_microcode; + const struct firmware *controller_microcode; + + u32 saved_regs[YDSXGR_NUM_SAVED_REGS]; + u32 saved_ydsxgr_mode; + u16 saved_dsxg_pci_regs[DSXG_PCI_NUM_SAVED_REGS]; +}; + +int snd_ymfpci_create(struct snd_card *card, + struct pci_dev *pci, + u16 old_legacy_ctrl); +void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); + +extern const struct dev_pm_ops snd_ymfpci_pm; + +int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device); +int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device); +int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device); +int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device); +int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch); +int snd_ymfpci_timer(struct snd_ymfpci *chip, int device); + +#endif /* __SOUND_YMFPCI_H */ |