#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
#include <sound/initval.h>
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK …
#endif
static int index[SNDRV_CARDS] = …;
static char *id[SNDRV_CARDS] = …;
static bool enable[SNDRV_CARDS] = …;
static bool reverb[SNDRV_CARDS];
static bool mge[SNDRV_CARDS];
static unsigned int dmaio = …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
module_param_hw(dmaio, uint, ioport, 0444);
MODULE_PARM_DESC(…) …;
#define SV_REG(sonic, x) …
#define SV_REG_CONTROL …
#define SV_ENHANCED …
#define SV_TEST …
#define SV_REVERB …
#define SV_WAVETABLE …
#define SV_INTA …
#define SV_RESET …
#define SV_REG_IRQMASK …
#define SV_DMAA_MASK …
#define SV_DMAC_MASK …
#define SV_SPEC_MASK …
#define SV_UD_MASK …
#define SV_MIDI_MASK …
#define SV_REG_STATUS …
#define SV_DMAA_IRQ …
#define SV_DMAC_IRQ …
#define SV_SPEC_IRQ …
#define SV_UD_IRQ …
#define SV_MIDI_IRQ …
#define SV_REG_INDEX …
#define SV_MCE …
#define SV_TRD …
#define SV_REG_DATA …
#define SV_IREG_LEFT_ADC …
#define SV_IREG_RIGHT_ADC …
#define SV_IREG_LEFT_AUX1 …
#define SV_IREG_RIGHT_AUX1 …
#define SV_IREG_LEFT_CD …
#define SV_IREG_RIGHT_CD …
#define SV_IREG_LEFT_LINE …
#define SV_IREG_RIGHT_LINE …
#define SV_IREG_MIC …
#define SV_IREG_GAME_PORT …
#define SV_IREG_LEFT_SYNTH …
#define SV_IREG_RIGHT_SYNTH …
#define SV_IREG_LEFT_AUX2 …
#define SV_IREG_RIGHT_AUX2 …
#define SV_IREG_LEFT_ANALOG …
#define SV_IREG_RIGHT_ANALOG …
#define SV_IREG_LEFT_PCM …
#define SV_IREG_RIGHT_PCM …
#define SV_IREG_DMA_DATA_FMT …
#define SV_IREG_PC_ENABLE …
#define SV_IREG_UD_BUTTON …
#define SV_IREG_REVISION …
#define SV_IREG_ADC_OUTPUT_CTRL …
#define SV_IREG_DMA_A_UPPER …
#define SV_IREG_DMA_A_LOWER …
#define SV_IREG_DMA_C_UPPER …
#define SV_IREG_DMA_C_LOWER …
#define SV_IREG_PCM_RATE_LOW …
#define SV_IREG_PCM_RATE_HIGH …
#define SV_IREG_SYNTH_RATE_LOW …
#define SV_IREG_SYNTH_RATE_HIGH …
#define SV_IREG_ADC_CLOCK …
#define SV_IREG_ADC_ALT_RATE …
#define SV_IREG_ADC_PLL_M …
#define SV_IREG_ADC_PLL_N …
#define SV_IREG_SYNTH_PLL_M …
#define SV_IREG_SYNTH_PLL_N …
#define SV_IREG_MPU401 …
#define SV_IREG_DRIVE_CTRL …
#define SV_IREG_SRS_SPACE …
#define SV_IREG_SRS_CENTER …
#define SV_IREG_WAVE_SOURCE …
#define SV_IREG_ANALOG_POWER …
#define SV_IREG_DIGITAL_POWER …
#define SV_IREG_ADC_PLL …
#define SV_IREG_SYNTH_PLL …
#define SV_DMA_ADDR0 …
#define SV_DMA_ADDR1 …
#define SV_DMA_ADDR2 …
#define SV_DMA_ADDR3 …
#define SV_DMA_COUNT0 …
#define SV_DMA_COUNT1 …
#define SV_DMA_COUNT2 …
#define SV_DMA_MODE …
#define SV_DMA_RESET …
#define SV_DMA_MASK …
#define SV_RECSRC_RESERVED …
#define SV_RECSRC_CD …
#define SV_RECSRC_DAC …
#define SV_RECSRC_AUX2 …
#define SV_RECSRC_LINE …
#define SV_RECSRC_AUX1 …
#define SV_RECSRC_MIC …
#define SV_RECSRC_OUT …
#define SV_FULLRATE …
#define SV_REFFREQUENCY …
#define SV_ADCMULT …
#define SV_MODE_PLAY …
#define SV_MODE_CAPTURE …
struct sonicvibes { … };
static const struct pci_device_id snd_sonic_ids[] = …;
MODULE_DEVICE_TABLE(pci, snd_sonic_ids);
static const struct snd_ratden sonicvibes_adc_clock = …;
static const struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = …;
static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic,
unsigned int addr,
unsigned int count)
{ … }
static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic,
unsigned int addr,
unsigned int count)
{ … }
static inline unsigned int snd_sonicvibes_getdmaa(struct sonicvibes * sonic)
{ … }
static inline unsigned int snd_sonicvibes_getdmac(struct sonicvibes * sonic)
{ … }
static void snd_sonicvibes_out1(struct sonicvibes * sonic,
unsigned char reg,
unsigned char value)
{ … }
static void snd_sonicvibes_out(struct sonicvibes * sonic,
unsigned char reg,
unsigned char value)
{ … }
static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg)
{ … }
static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg)
{ … }
#if 0
static void snd_sonicvibes_debug(struct sonicvibes * sonic)
{
dev_dbg(sonic->card->dev,
"SV REGS: INDEX = 0x%02x STATUS = 0x%02x\n",
inb(SV_REG(sonic, INDEX)), inb(SV_REG(sonic, STATUS)));
dev_dbg(sonic->card->dev,
" 0x00: left input = 0x%02x 0x20: synth rate low = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x00), snd_sonicvibes_in(sonic, 0x20));
dev_dbg(sonic->card->dev,
" 0x01: right input = 0x%02x 0x21: synth rate high = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x01), snd_sonicvibes_in(sonic, 0x21));
dev_dbg(sonic->card->dev,
" 0x02: left AUX1 = 0x%02x 0x22: ADC clock = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x02), snd_sonicvibes_in(sonic, 0x22));
dev_dbg(sonic->card->dev,
" 0x03: right AUX1 = 0x%02x 0x23: ADC alt rate = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x03), snd_sonicvibes_in(sonic, 0x23));
dev_dbg(sonic->card->dev,
" 0x04: left CD = 0x%02x 0x24: ADC pll M = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x04), snd_sonicvibes_in(sonic, 0x24));
dev_dbg(sonic->card->dev,
" 0x05: right CD = 0x%02x 0x25: ADC pll N = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x05), snd_sonicvibes_in(sonic, 0x25));
dev_dbg(sonic->card->dev,
" 0x06: left line = 0x%02x 0x26: Synth pll M = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x06), snd_sonicvibes_in(sonic, 0x26));
dev_dbg(sonic->card->dev,
" 0x07: right line = 0x%02x 0x27: Synth pll N = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x07), snd_sonicvibes_in(sonic, 0x27));
dev_dbg(sonic->card->dev,
" 0x08: MIC = 0x%02x 0x28: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x08), snd_sonicvibes_in(sonic, 0x28));
dev_dbg(sonic->card->dev,
" 0x09: Game port = 0x%02x 0x29: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x09), snd_sonicvibes_in(sonic, 0x29));
dev_dbg(sonic->card->dev,
" 0x0a: left synth = 0x%02x 0x2a: MPU401 = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x0a), snd_sonicvibes_in(sonic, 0x2a));
dev_dbg(sonic->card->dev,
" 0x0b: right synth = 0x%02x 0x2b: drive ctrl = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x0b), snd_sonicvibes_in(sonic, 0x2b));
dev_dbg(sonic->card->dev,
" 0x0c: left AUX2 = 0x%02x 0x2c: SRS space = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x0c), snd_sonicvibes_in(sonic, 0x2c));
dev_dbg(sonic->card->dev,
" 0x0d: right AUX2 = 0x%02x 0x2d: SRS center = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x0d), snd_sonicvibes_in(sonic, 0x2d));
dev_dbg(sonic->card->dev,
" 0x0e: left analog = 0x%02x 0x2e: wave source = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x0e), snd_sonicvibes_in(sonic, 0x2e));
dev_dbg(sonic->card->dev,
" 0x0f: right analog = 0x%02x 0x2f: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x0f), snd_sonicvibes_in(sonic, 0x2f));
dev_dbg(sonic->card->dev,
" 0x10: left PCM = 0x%02x 0x30: analog power = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x10), snd_sonicvibes_in(sonic, 0x30));
dev_dbg(sonic->card->dev,
" 0x11: right PCM = 0x%02x 0x31: analog power = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x11), snd_sonicvibes_in(sonic, 0x31));
dev_dbg(sonic->card->dev,
" 0x12: DMA data format = 0x%02x 0x32: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x12), snd_sonicvibes_in(sonic, 0x32));
dev_dbg(sonic->card->dev,
" 0x13: P/C enable = 0x%02x 0x33: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x13), snd_sonicvibes_in(sonic, 0x33));
dev_dbg(sonic->card->dev,
" 0x14: U/D button = 0x%02x 0x34: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x14), snd_sonicvibes_in(sonic, 0x34));
dev_dbg(sonic->card->dev,
" 0x15: revision = 0x%02x 0x35: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x15), snd_sonicvibes_in(sonic, 0x35));
dev_dbg(sonic->card->dev,
" 0x16: ADC output ctrl = 0x%02x 0x36: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x16), snd_sonicvibes_in(sonic, 0x36));
dev_dbg(sonic->card->dev,
" 0x17: --- = 0x%02x 0x37: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x17), snd_sonicvibes_in(sonic, 0x37));
dev_dbg(sonic->card->dev,
" 0x18: DMA A upper cnt = 0x%02x 0x38: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x18), snd_sonicvibes_in(sonic, 0x38));
dev_dbg(sonic->card->dev,
" 0x19: DMA A lower cnt = 0x%02x 0x39: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x19), snd_sonicvibes_in(sonic, 0x39));
dev_dbg(sonic->card->dev,
" 0x1a: --- = 0x%02x 0x3a: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x1a), snd_sonicvibes_in(sonic, 0x3a));
dev_dbg(sonic->card->dev,
" 0x1b: --- = 0x%02x 0x3b: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x1b), snd_sonicvibes_in(sonic, 0x3b));
dev_dbg(sonic->card->dev,
" 0x1c: DMA C upper cnt = 0x%02x 0x3c: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x1c), snd_sonicvibes_in(sonic, 0x3c));
dev_dbg(sonic->card->dev,
" 0x1d: DMA C upper cnt = 0x%02x 0x3d: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x1d), snd_sonicvibes_in(sonic, 0x3d));
dev_dbg(sonic->card->dev,
" 0x1e: PCM rate low = 0x%02x 0x3e: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x1e), snd_sonicvibes_in(sonic, 0x3e));
dev_dbg(sonic->card->dev,
" 0x1f: PCM rate high = 0x%02x 0x3f: --- = 0x%02x\n",
snd_sonicvibes_in(sonic, 0x1f), snd_sonicvibes_in(sonic, 0x3f));
}
#endif
static void snd_sonicvibes_setfmt(struct sonicvibes * sonic,
unsigned char mask,
unsigned char value)
{ … }
static void snd_sonicvibes_pll(unsigned int rate,
unsigned int *res_r,
unsigned int *res_m,
unsigned int *res_n)
{ … }
static void snd_sonicvibes_setpll(struct sonicvibes * sonic,
unsigned char reg,
unsigned int rate)
{ … }
static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int rate)
{ … }
static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{ … }
static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int rate)
{ … }
static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd)
{ … }
static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id)
{ … }
static int snd_sonicvibes_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{ … }
static int snd_sonicvibes_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{ … }
static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream)
{ … }
static int snd_sonicvibes_capture_prepare(struct snd_pcm_substream *substream)
{ … }
static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(struct snd_pcm_substream *substream)
{ … }
static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(struct snd_pcm_substream *substream)
{ … }
static const struct snd_pcm_hardware snd_sonicvibes_playback = …;
static const struct snd_pcm_hardware snd_sonicvibes_capture = …;
static int snd_sonicvibes_playback_open(struct snd_pcm_substream *substream)
{ … }
static int snd_sonicvibes_capture_open(struct snd_pcm_substream *substream)
{ … }
static int snd_sonicvibes_playback_close(struct snd_pcm_substream *substream)
{ … }
static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream)
{ … }
static const struct snd_pcm_ops snd_sonicvibes_playback_ops = …;
static const struct snd_pcm_ops snd_sonicvibes_capture_ops = …;
static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device)
{ … }
#define SONICVIBES_MUX(xname, xindex) …
static int snd_sonicvibes_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ … }
static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ … }
#define SONICVIBES_SINGLE(xname, xindex, reg, shift, mask, invert) …
static int snd_sonicvibes_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ … }
static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ … }
#define SONICVIBES_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) …
static int snd_sonicvibes_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ … }
static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ … }
static const struct snd_kcontrol_new snd_sonicvibes_controls[] = …;
static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
{ … }
static int snd_sonicvibes_mixer(struct sonicvibes *sonic)
{ … }
static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{ … }
static void snd_sonicvibes_proc_init(struct sonicvibes *sonic)
{ … }
#ifdef SUPPORT_JOYSTICK
static const struct snd_kcontrol_new snd_sonicvibes_game_control = …;
static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
{ … }
static void snd_sonicvibes_free_gameport(struct sonicvibes *sonic)
{ … }
#else
static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { return -ENOSYS; }
static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
#endif
static void snd_sonicvibes_free(struct snd_card *card)
{ … }
static int snd_sonicvibes_create(struct snd_card *card,
struct pci_dev *pci,
int reverb,
int mge)
{ … }
static const struct snd_kcontrol_new snd_sonicvibes_midi_controls[] = …;
static int snd_sonicvibes_midi_input_open(struct snd_mpu401 * mpu)
{ … }
static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
{ … }
static int snd_sonicvibes_midi(struct sonicvibes *sonic,
struct snd_rawmidi *rmidi)
{ … }
static int __snd_sonic_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{ … }
static int snd_sonic_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{ … }
static struct pci_driver sonicvibes_driver = …;
module_pci_driver(…) …;