#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
+#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/control.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
-#define SNDRV_GET_ID
#include <sound/initval.h>
#include <asm/io.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("S3 SonicVibes PCI");
MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{S3,SonicVibes PCI}}");
+MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
-#ifndef PCI_VENDOR_ID_S3
-#define PCI_VENDOR_ID_S3 0x5333
-#endif
-#ifndef PCI_DEVICE_ID_S3_SONICVIBES
-#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
#endif
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static int mge[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static unsigned int dmaio = 0x7a00; /* DDMA i/o address */
-MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
-MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
+module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_PARM(reverb, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(reverb, bool, NULL, 0444);
MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(reverb, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
-MODULE_PARM(mge, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(mge, bool, NULL, 0444);
MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(mge, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
-MODULE_PARM(dmaio, "i");
+module_param(dmaio, uint, 0444);
MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(dmaio, "global," SNDRV_PORT_DESC);
/*
* Enhanced port direct registers
*/
-typedef struct _snd_sonicvibes sonicvibes_t;
-#define chip_t sonicvibes_t
-
-struct _snd_sonicvibes {
+struct sonicvibes {
unsigned long dma1size;
unsigned long dma2size;
int irq;
unsigned long sb_port;
- struct resource *res_sb_port;
unsigned long enh_port;
- struct resource *res_enh_port;
unsigned long synth_port;
- struct resource *res_synth_port;
unsigned long midi_port;
- struct resource *res_midi_port;
unsigned long game_port;
unsigned int dmaa_port;
struct resource *res_dmaa;
unsigned int mode;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
- snd_rawmidi_t *rmidi;
- snd_hwdep_t *fmsynth; /* S3FM */
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_rawmidi *rmidi;
+ struct snd_hwdep *fmsynth; /* S3FM */
spinlock_t reg_lock;
unsigned int p_dma_size;
unsigned int c_dma_size;
- snd_kcontrol_t *master_mute;
- snd_kcontrol_t *master_volume;
+ struct snd_kcontrol *master_mute;
+ struct snd_kcontrol *master_volume;
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif
};
MODULE_DEVICE_TABLE(pci, snd_sonic_ids);
-static ratden_t sonicvibes_adc_clock = {
+static struct snd_ratden sonicvibes_adc_clock = {
.num_min = 4000 * 65536,
.num_max = 48000UL * 65536,
.num_step = 1,
.den = 65536,
};
-static snd_pcm_hw_constraint_ratdens_t snd_sonicvibes_hw_constraints_adc_clock = {
+static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = {
.nrats = 1,
.rats = &sonicvibes_adc_clock,
};
* common I/O routines
*/
-static inline void snd_sonicvibes_setdmaa(sonicvibes_t * sonic,
+static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic,
unsigned int addr,
unsigned int count)
{
#endif
}
-static inline void snd_sonicvibes_setdmac(sonicvibes_t * sonic,
+static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic,
unsigned int addr,
unsigned int count)
{
#endif
}
-static inline unsigned int snd_sonicvibes_getdmaa(sonicvibes_t * sonic)
+static inline unsigned int snd_sonicvibes_getdmaa(struct sonicvibes * sonic)
{
return (inl(sonic->dmaa_port + SV_DMA_COUNT0) & 0xffffff) + 1;
}
-static inline unsigned int snd_sonicvibes_getdmac(sonicvibes_t * sonic)
+static inline unsigned int snd_sonicvibes_getdmac(struct sonicvibes * sonic)
{
/* note: dmac is working in word mode!!! */
return ((inl(sonic->dmac_port + SV_DMA_COUNT0) & 0xffffff) + 1) << 1;
}
-static void snd_sonicvibes_out1(sonicvibes_t * sonic,
+static void snd_sonicvibes_out1(struct sonicvibes * sonic,
unsigned char reg,
unsigned char value)
{
udelay(10);
}
-static void snd_sonicvibes_out(sonicvibes_t * sonic,
+static void snd_sonicvibes_out(struct sonicvibes * sonic,
unsigned char reg,
unsigned char value)
{
spin_unlock_irqrestore(&sonic->reg_lock, flags);
}
-static unsigned char snd_sonicvibes_in1(sonicvibes_t * sonic, unsigned char reg)
+static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg)
{
unsigned char value;
return value;
}
-static unsigned char snd_sonicvibes_in(sonicvibes_t * sonic, unsigned char reg)
+static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg)
{
unsigned long flags;
unsigned char value;
return value;
}
-#ifdef CONFIG_SND_DEBUG
-void snd_sonicvibes_debug(sonicvibes_t * sonic)
+#if 0
+static void snd_sonicvibes_debug(struct sonicvibes * sonic)
{
printk("SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX)));
printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS)));
#endif
-static void snd_sonicvibes_setfmt(sonicvibes_t * sonic,
+static void snd_sonicvibes_setfmt(struct sonicvibes * sonic,
unsigned char mask,
unsigned char value)
{
#endif
}
-static void snd_sonicvibes_setpll(sonicvibes_t * sonic,
+static void snd_sonicvibes_setpll(struct sonicvibes * sonic,
unsigned char reg,
unsigned int rate)
{
}
}
-static void snd_sonicvibes_set_adc_rate(sonicvibes_t * sonic, unsigned int rate)
+static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int rate)
{
unsigned long flags;
unsigned int div;
spin_unlock_irqrestore(&sonic->reg_lock, flags);
}
-static int snd_sonicvibes_hw_constraint_dac_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
unsigned int rate, div, r, m, n;
return 0;
}
-static void snd_sonicvibes_set_dac_rate(sonicvibes_t * sonic, unsigned int rate)
+static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int rate)
{
unsigned int div;
unsigned long flags;
spin_unlock_irqrestore(&sonic->reg_lock, flags);
}
-static int snd_sonicvibes_trigger(sonicvibes_t * sonic, int what, int cmd)
+static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd)
{
int result = 0;
static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, dev_id, return IRQ_NONE);
+ struct sonicvibes *sonic = dev_id;
unsigned char status;
status = inb(SV_REG(sonic, STATUS));
return IRQ_NONE;
if (status == 0xff) { /* failure */
outb(sonic->irqmask = ~0, SV_REG(sonic, IRQMASK));
- snd_printk("IRQ failure - interrupts disabled!!\n");
+ snd_printk(KERN_ERR "IRQ failure - interrupts disabled!!\n");
return IRQ_HANDLED;
}
if (sonic->pcm) {
* PCM part
*/
-static int snd_sonicvibes_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_sonicvibes_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
return snd_sonicvibes_trigger(sonic, 1, cmd);
}
-static int snd_sonicvibes_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_sonicvibes_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
return snd_sonicvibes_trigger(sonic, 2, cmd);
}
-static int snd_sonicvibes_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_sonicvibes_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_sonicvibes_hw_free(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_sonicvibes_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream)
{
- unsigned long flags;
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned char fmt = 0;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
fmt |= 2;
snd_sonicvibes_setfmt(sonic, ~3, fmt);
snd_sonicvibes_set_dac_rate(sonic, runtime->rate);
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
snd_sonicvibes_setdmaa(sonic, runtime->dma_addr, size);
snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_UPPER, count >> 8);
snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_LOWER, count);
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
return 0;
}
-static int snd_sonicvibes_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_capture_prepare(struct snd_pcm_substream *substream)
{
- unsigned long flags;
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned char fmt = 0;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
fmt |= 0x20;
snd_sonicvibes_setfmt(sonic, ~0x30, fmt);
snd_sonicvibes_set_adc_rate(sonic, runtime->rate);
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
snd_sonicvibes_setdmac(sonic, runtime->dma_addr, size);
snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_UPPER, count >> 8);
snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_LOWER, count);
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
return 0;
}
-static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(sonic->enable & 1))
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(sonic->enable & 2))
return 0;
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_hardware_t snd_sonicvibes_playback =
+static struct snd_pcm_hardware snd_sonicvibes_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_sonicvibes_capture =
+static struct snd_pcm_hardware snd_sonicvibes_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
.fifo_size = 0,
};
-static int snd_sonicvibes_playback_open(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_playback_open(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
sonic->mode |= SV_MODE_PLAY;
sonic->playback_substream = substream;
runtime->hw = snd_sonicvibes_playback;
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, snd_sonicvibes_hw_constraint_dac_rate, 0, SNDRV_PCM_HW_PARAM_RATE, -1);
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, snd_sonicvibes_hw_constraint_dac_rate, NULL, SNDRV_PCM_HW_PARAM_RATE, -1);
return 0;
}
-static int snd_sonicvibes_capture_open(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_capture_open(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
sonic->mode |= SV_MODE_CAPTURE;
sonic->capture_substream = substream;
return 0;
}
-static int snd_sonicvibes_playback_close(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_playback_close(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
sonic->playback_substream = NULL;
sonic->mode &= ~SV_MODE_PLAY;
return 0;
}
-static int snd_sonicvibes_capture_close(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
sonic->capture_substream = NULL;
sonic->mode &= ~SV_MODE_CAPTURE;
return 0;
}
-static snd_pcm_ops_t snd_sonicvibes_playback_ops = {
+static struct snd_pcm_ops snd_sonicvibes_playback_ops = {
.open = snd_sonicvibes_playback_open,
.close = snd_sonicvibes_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.pointer = snd_sonicvibes_playback_pointer,
};
-static snd_pcm_ops_t snd_sonicvibes_capture_ops = {
+static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
.open = snd_sonicvibes_capture_open,
.close = snd_sonicvibes_capture_close,
.ioctl = snd_pcm_lib_ioctl,
.pointer = snd_sonicvibes_capture_pointer,
};
-static void snd_sonicvibes_pcm_free(snd_pcm_t *pcm)
-{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, pcm->private_data, return);
- sonic->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_sonicvibes_pcm(sonicvibes_t * sonic, int device, snd_pcm_t ** rpcm)
+static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sonicvibes_capture_ops);
pcm->private_data = sonic;
- pcm->private_free = snd_sonicvibes_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "S3 SonicVibes");
sonic->pcm = pcm;
.info = snd_sonicvibes_info_mux, \
.get = snd_sonicvibes_get_mux, .put = snd_sonicvibes_put_mux }
-static int snd_sonicvibes_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sonicvibes_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[7] = {
"CD", "PCM", "Aux1", "Line", "Aux0", "Mic", "Mix"
return 0;
}
-static int snd_sonicvibes_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
return 0;
}
-static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
unsigned short left, right, oval1, oval2;
int change;
return -EINVAL;
left = (ucontrol->value.enumerated.item[0] + 1) << 5;
right = (ucontrol->value.enumerated.item[1] + 1) << 5;
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC);
oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC);
left = (oval1 & ~SV_RECSRC_OUT) | left;
change = left != oval1 || right != oval2;
snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left);
snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right);
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
return change;
}
.get = snd_sonicvibes_get_single, .put = snd_sonicvibes_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_sonicvibes_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sonicvibes_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
return 0;
}
-static int snd_sonicvibes_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0xff;
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask;
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
if (invert)
ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
return 0;
}
-static int snd_sonicvibes_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
if (invert)
val = mask - val;
val <<= shift;
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
oval = snd_sonicvibes_in1(sonic, reg);
val = (oval & ~(mask << shift)) | val;
change = val != oval;
snd_sonicvibes_out1(sonic, reg, val);
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
return change;
}
.get = snd_sonicvibes_get_double, .put = snd_sonicvibes_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_sonicvibes_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sonicvibes_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
return 0;
}
-static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff;
int invert = (kcontrol->private_value >> 22) & 1;
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask;
ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask;
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
if (invert) {
ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
return 0;
}
-static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
}
val1 <<= shift_left;
val2 <<= shift_right;
- spin_lock_irqsave(&sonic->reg_lock, flags);
+ spin_lock_irq(&sonic->reg_lock);
oval1 = snd_sonicvibes_in1(sonic, left_reg);
oval2 = snd_sonicvibes_in1(sonic, right_reg);
val1 = (oval1 & ~(mask << shift_left)) | val1;
change = val1 != oval1 || val2 != oval2;
snd_sonicvibes_out1(sonic, left_reg, val1);
snd_sonicvibes_out1(sonic, right_reg, val2);
- spin_unlock_irqrestore(&sonic->reg_lock, flags);
+ spin_unlock_irq(&sonic->reg_lock);
return change;
}
-#define SONICVIBES_CONTROLS (sizeof(snd_sonicvibes_controls)/sizeof(snd_kcontrol_new_t))
-
-static snd_kcontrol_new_t snd_sonicvibes_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {
SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
SONICVIBES_MUX("Capture Source", 0)
};
-static void snd_sonicvibes_master_free(snd_kcontrol_t *kcontrol)
+static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, _snd_kcontrol_chip(kcontrol), return);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
sonic->master_mute = NULL;
sonic->master_volume = NULL;
}
-static int __devinit snd_sonicvibes_mixer(sonicvibes_t * sonic)
+static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic)
{
- snd_card_t *card;
- snd_kcontrol_t *kctl;
+ struct snd_card *card;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
card = sonic->card;
strcpy(card->mixername, "S3 SonicVibes");
- for (idx = 0; idx < SONICVIBES_CONTROLS; idx++) {
+ for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0)
return err;
switch (idx) {
*/
-static void snd_sonicvibes_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, entry->private_data, return);
+ struct sonicvibes *sonic = entry->private_data;
unsigned char tmp;
tmp = sonic->srs_space & 0x0f;
snd_iprintf(buffer, "MIDI to ext. Tx : %s\n", tmp & 0x04 ? "on" : "off");
}
-static void __devinit snd_sonicvibes_proc_init(sonicvibes_t * sonic)
+static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))
snd_info_set_text_ops(entry, sonic, 1024, snd_sonicvibes_proc_read);
*/
-static snd_kcontrol_new_t snd_sonicvibes_game_control __devinitdata =
+#ifdef SUPPORT_JOYSTICK
+static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =
SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
-static int snd_sonicvibes_free(sonicvibes_t *sonic)
+static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (sonic->gameport.io)
- gameport_unregister_port(&sonic->gameport);
+ struct gameport *gp;
+
+ sonic->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "SonicVibes Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));
+ gameport_set_dev_parent(gp, &sonic->pci->dev);
+ gp->io = sonic->game_port;
+
+ gameport_register_port(gp);
+
+ snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
+
+ return 0;
+}
+
+static void snd_sonicvibes_free_gameport(struct sonicvibes *sonic)
+{
+ if (sonic->gameport) {
+ gameport_unregister_port(sonic->gameport);
+ sonic->gameport = NULL;
+ }
+}
+#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 int snd_sonicvibes_free(struct sonicvibes *sonic)
+{
+ snd_sonicvibes_free_gameport(sonic);
pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
- if (sonic->res_sb_port) {
- release_resource(sonic->res_sb_port);
- kfree_nocheck(sonic->res_sb_port);
- }
- if (sonic->res_enh_port) {
- release_resource(sonic->res_enh_port);
- kfree_nocheck(sonic->res_enh_port);
- }
- if (sonic->res_synth_port) {
- release_resource(sonic->res_synth_port);
- kfree_nocheck(sonic->res_synth_port);
- }
- if (sonic->res_midi_port) {
- release_resource(sonic->res_midi_port);
- kfree_nocheck(sonic->res_midi_port);
- }
- if (sonic->res_dmaa) {
- release_resource(sonic->res_dmaa);
- kfree_nocheck(sonic->res_dmaa);
- }
- if (sonic->res_dmac) {
- release_resource(sonic->res_dmac);
- kfree_nocheck(sonic->res_dmac);
- }
if (sonic->irq >= 0)
free_irq(sonic->irq, (void *)sonic);
- snd_magic_kfree(sonic);
+ release_and_free_resource(sonic->res_dmaa);
+ release_and_free_resource(sonic->res_dmac);
+ pci_release_regions(sonic->pci);
+ pci_disable_device(sonic->pci);
+ kfree(sonic);
return 0;
}
-static int snd_sonicvibes_dev_free(snd_device_t *device)
+static int snd_sonicvibes_dev_free(struct snd_device *device)
{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, device->device_data, return -ENXIO);
+ struct sonicvibes *sonic = device->device_data;
return snd_sonicvibes_free(sonic);
}
-static int __devinit snd_sonicvibes_create(snd_card_t * card,
+static int __devinit snd_sonicvibes_create(struct snd_card *card,
struct pci_dev *pci,
int reverb,
int mge,
- sonicvibes_t ** rsonic)
+ struct sonicvibes ** rsonic)
{
- sonicvibes_t *sonic;
+ struct sonicvibes *sonic;
unsigned int dmaa, dmac;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_sonicvibes_dev_free,
};
/* check, if we can restrict PCI DMA transfers to 24 bits */
if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
- snd_printk("architecture does not support 24bit PCI busmaster DMA\n");
+ snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
+ pci_disable_device(pci);
return -ENXIO;
}
- sonic = snd_magic_kcalloc(sonicvibes_t, 0, GFP_KERNEL);
- if (sonic == NULL)
+ sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
+ if (sonic == NULL) {
+ pci_disable_device(pci);
return -ENOMEM;
+ }
spin_lock_init(&sonic->reg_lock);
sonic->card = card;
sonic->pci = pci;
sonic->irq = -1;
- sonic->sb_port = pci_resource_start(pci, 0);
- if ((sonic->res_sb_port = request_region(sonic->sb_port, 0x10, "S3 SonicVibes SB")) == NULL) {
- snd_printk("unable to grab SB port at 0x%lx-0x%lx\n", sonic->sb_port, sonic->sb_port + 0x10 - 1);
- snd_sonicvibes_free(sonic);
- return -EBUSY;
+
+ if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) {
+ kfree(sonic);
+ pci_disable_device(pci);
+ return err;
}
+
+ sonic->sb_port = pci_resource_start(pci, 0);
sonic->enh_port = pci_resource_start(pci, 1);
- if ((sonic->res_enh_port = request_region(sonic->enh_port, 0x10, "S3 SonicVibes Enhanced")) == NULL) {
- snd_printk("unable to grab PCM port at 0x%lx-0x%lx\n", sonic->enh_port, sonic->enh_port + 0x10 - 1);
- snd_sonicvibes_free(sonic);
- return -EBUSY;
- }
sonic->synth_port = pci_resource_start(pci, 2);
- if ((sonic->res_synth_port = request_region(sonic->synth_port, 4, "S3 SonicVibes Synth")) == NULL) {
- snd_printk("unable to grab synth port at 0x%lx-0x%lx\n", sonic->synth_port, sonic->synth_port + 4 - 1);
- snd_sonicvibes_free(sonic);
- return -EBUSY;
- }
sonic->midi_port = pci_resource_start(pci, 3);
- if ((sonic->res_midi_port = request_region(sonic->midi_port, 4, "S3 SonicVibes Midi")) == NULL) {
- snd_printk("unable to grab MIDI port at 0x%lx-0x%lx\n", sonic->midi_port, sonic->midi_port + 4 - 1);
- snd_sonicvibes_free(sonic);
- return -EBUSY;
- }
sonic->game_port = pci_resource_start(pci, 4);
+
if (request_irq(pci->irq, snd_sonicvibes_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", (void *)sonic)) {
- snd_printk("unable to grab IRQ %d\n", pci->irq);
+ snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_sonicvibes_free(sonic);
return -EBUSY;
}
if (!dmaa) {
dmaa = dmaio;
dmaio += 0x10;
- snd_printk("BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa);
+ snd_printk(KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa);
}
if (!dmac) {
dmac = dmaio;
dmaio += 0x10;
- snd_printk("BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac);
+ snd_printk(KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac);
}
pci_write_config_dword(pci, 0x40, dmaa);
pci_write_config_dword(pci, 0x48, dmac);
if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) {
snd_sonicvibes_free(sonic);
- snd_printk("unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1);
+ snd_printk(KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1);
return -EBUSY;
}
if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) {
snd_sonicvibes_free(sonic);
- snd_printk("unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1);
+ snd_printk(KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1);
return -EBUSY;
}
snd_sonicvibes_debug(sonic);
#endif
sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
- snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
- snd_sonicvibes_proc_init(sonic);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) {
snd_sonicvibes_free(sonic);
return err;
}
+ snd_sonicvibes_proc_init(sonic);
+
snd_card_set_dev(card, &pci->dev);
*rsonic = sonic;
* MIDI section
*/
-#define SONICVIBES_MIDI_CONTROLS (sizeof(snd_sonicvibes_midi_controls)/sizeof(snd_kcontrol_new_t))
-
-static snd_kcontrol_new_t snd_sonicvibes_midi_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
SONICVIBES_SINGLE("SonicVibes External Tx", 0, SV_IREG_MPU401, 2, 1, 0)
};
-static int snd_sonicvibes_midi_input_open(mpu401_t * mpu)
+static int snd_sonicvibes_midi_input_open(struct snd_mpu401 * mpu)
{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, mpu->private_data, return -EIO);
+ struct sonicvibes *sonic = mpu->private_data;
outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
return 0;
}
-static void snd_sonicvibes_midi_input_close(mpu401_t * mpu)
+static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
{
- sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, mpu->private_data, return);
+ struct sonicvibes *sonic = mpu->private_data;
outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
}
-static int __devinit snd_sonicvibes_midi(sonicvibes_t * sonic, snd_rawmidi_t * rmidi)
+static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
+ struct snd_rawmidi *rmidi)
{
- mpu401_t * mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return -ENXIO);
- snd_card_t *card = sonic->card;
- snd_rawmidi_str_t *dir;
+ struct snd_mpu401 * mpu = rmidi->private_data;
+ struct snd_card *card = sonic->card;
+ struct snd_rawmidi_str *dir;
unsigned int idx;
int err;
mpu->open_input = snd_sonicvibes_midi_input_open;
mpu->close_input = snd_sonicvibes_midi_input_close;
dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
- for (idx = 0; idx < SONICVIBES_MIDI_CONTROLS; idx++)
+ for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++)
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0)
return err;
return 0;
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- sonicvibes_t *sonic;
- snd_rawmidi_t *midi_uart;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct sonicvibes *sonic;
+ struct snd_rawmidi *midi_uart;
+ struct snd_opl3 *opl3;
int idx, err;
if (dev >= SNDRV_CARDS)
snd_card_free(card);
return err;
}
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- sonic->gameport.io = sonic->game_port;
- gameport_register_port(&sonic->gameport);
-#endif
+
+ snd_sonicvibes_create_gameport(sonic);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
static int __init alsa_card_sonicvibes_init(void)
{
- int err;
-
- if ((err = pci_module_init(&driver)) < 0) {
-#ifdef MODULE
- printk(KERN_ERR "S3 SonicVibes soundcard not found or device busy\n");
-#endif
- return err;
- }
- return 0;
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_sonicvibes_exit(void)
module_init(alsa_card_sonicvibes_init)
module_exit(alsa_card_sonicvibes_exit)
-
-#ifndef MODULE
-
-/* format is: snd-sonicvibes=enable,index,id,
- reverb,mge,dmaio */
-
-static int __init alsa_card_sonicvibes_setup(char *str)
-{
- static unsigned __initdata nr_dev = 0;
-
- if (nr_dev >= SNDRV_CARDS)
- return 0;
- (void)(get_option(&str,&enable[nr_dev]) == 2 &&
- get_option(&str,&index[nr_dev]) == 2 &&
- get_id(&str,&id[nr_dev]) == 2 &&
- get_option(&str,&reverb[nr_dev]) == 2 &&
- get_option(&str,&mge[nr_dev]) == 2 &&
- get_option(&str,(int *)&dmaio) == 2);
- nr_dev++;
- return 1;
-}
-
-__setup("snd-sonicvibes=", alsa_card_sonicvibes_setup);
-
-#endif /* ifndef MODULE */