MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Cirrus Logic CS4281");
MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Cirrus Logic,CS4281}}");
+MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
module_param_array(index, int, boot_devs, 0444);
MODULE_PARM_DESC(index, "Index value for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
module_param_array(id, charp, boot_devs, 0444);
MODULE_PARM_DESC(id, "ID string for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
module_param_array(enable, bool, boot_devs, 0444);
MODULE_PARM_DESC(enable, "Enable CS4281 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
module_param_array(dual_codec, bool, boot_devs, 0444);
MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
-MODULE_PARM_SYNTAX(dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
/*
*
*
*/
-#define chip_t cs4281_t
-
typedef struct snd_cs4281 cs4281_t;
typedef struct snd_cs4281_dma cs4281_dma_t;
unsigned long ba1; /* virtual (accessible) address */
unsigned long ba0_addr;
unsigned long ba1_addr;
- struct resource *ba0_res;
- struct resource *ba1_res;
int dual_codec;
* 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
* 5. if DCV not cleared, break and return error
*/
- cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+ cs4281_t *chip = ac97->private_data;
int count;
/*
static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
unsigned short reg)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return -ENXIO);
+ cs4281_t *chip = ac97->private_data;
int count;
unsigned short result;
// FIXME: volatile is necessary in the following due to a bug of
{
cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
cs4281_t *chip = snd_pcm_substream_chip(substream);
- unsigned long flags;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dma->valDCR |= BA0_DCR_MSK;
dma->valFCR &= ~BA0_FCR_FEN;
break;
default:
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
return -EINVAL;
}
snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
return 0;
}
snd_pcm_runtime_t *runtime = substream->runtime;
cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
cs4281_t *chip = snd_pcm_substream_chip(substream);
- unsigned long flags;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
snd_cs4281_mode(chip, dma, runtime, 0, 1);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
snd_pcm_runtime_t *runtime = substream->runtime;
cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
cs4281_t *chip = snd_pcm_substream_chip(substream);
- unsigned long flags;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
snd_cs4281_mode(chip, dma, runtime, 1, 1);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
static void snd_cs4281_pcm_free(snd_pcm_t *pcm)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, pcm->private_data, return);
+ cs4281_t *chip = pcm->private_data;
chip->pcm = NULL;
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static void snd_cs4281_mixer_free_ac97_bus(ac97_bus_t *bus)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, bus->private_data, return);
+ cs4281_t *chip = bus->private_data;
chip->ac97_bus = NULL;
}
static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+ cs4281_t *chip = ac97->private_data;
if (ac97->num)
chip->ac97_secondary = NULL;
else
static int __devinit snd_cs4281_mixer(cs4281_t * chip)
{
snd_card_t *card = chip->card;
- ac97_bus_t bus;
- ac97_t ac97;
+ ac97_template_t ac97;
int err;
+ static ac97_bus_ops_t ops = {
+ .write = snd_cs4281_ac97_write,
+ .read = snd_cs4281_ac97_read,
+ };
- memset(&bus, 0, sizeof(bus));
- bus.write = snd_cs4281_ac97_write;
- bus.read = snd_cs4281_ac97_read;
- bus.private_data = chip;
- bus.private_free = snd_cs4281_mixer_free_ac97_bus;
- if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+ if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
return err;
+ chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus;
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
static void snd_cs4281_proc_read(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return);
+ cs4281_t *chip = entry->private_data;
snd_iprintf(buffer, "Cirrus Logic CS4281\n\n");
snd_iprintf(buffer, "Spurious half IRQs : %u\n", chip->spurious_dhtc_irq);
unsigned long count, unsigned long pos)
{
long size;
- cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+ cs4281_t *chip = entry->private_data;
size = count;
if (pos + size > CS4281_BA0_SIZE)
unsigned long count, unsigned long pos)
{
long size;
- cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+ cs4281_t *chip = entry->private_data;
size = count;
if (pos + size > CS4281_BA1_SIZE)
cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
cs4281_t *chip;
snd_assert(gp, return);
- chip = snd_magic_cast(cs4281_t, gp->chip, return);
+ chip = gp->chip;
snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
}
cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
cs4281_t *chip;
snd_assert(gp, return 0);
- chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+ chip = gp->chip;
return snd_cs4281_peekBA0(chip, BA0_JSPT);
}
unsigned js1, js2, jst;
snd_assert(gp, return 0);
- chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+ chip = gp->chip;
js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
/* PCI interface - D3 state */
pci_set_power_state(chip->pci, 3);
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void *)chip);
if (chip->ba0)
iounmap((void *) chip->ba0);
if (chip->ba1)
iounmap((void *) chip->ba1);
- if (chip->ba0_res) {
- release_resource(chip->ba0_res);
- kfree_nocheck(chip->ba0_res);
- }
- if (chip->ba1_res) {
- release_resource(chip->ba1_res);
- kfree_nocheck(chip->ba1_res);
- }
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ pci_release_regions(chip->pci);
- snd_magic_kfree(chip);
+ kfree(chip);
return 0;
}
static int snd_cs4281_dev_free(snd_device_t *device)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, device->device_data, return -ENXIO);
+ cs4281_t *chip = device->device_data;
return snd_cs4281_free(chip);
}
*rchip = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = snd_magic_kcalloc(cs4281_t, 0, GFP_KERNEL);
+ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- chip->ba0_addr = pci_resource_start(pci, 0);
- chip->ba1_addr = pci_resource_start(pci, 1);
pci_set_master(pci);
if (dual_codec < 0 || dual_codec > 3) {
snd_printk(KERN_ERR "invalid dual_codec option %d\n", dual_codec);
}
chip->dual_codec = dual_codec;
- if ((chip->ba0_res = request_mem_region(chip->ba0_addr, CS4281_BA0_SIZE, "CS4281 BA0")) == NULL) {
- snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba0_addr, chip->ba0_addr + CS4281_BA0_SIZE - 1);
- snd_cs4281_free(chip);
- return -ENOMEM;
- }
- if ((chip->ba1_res = request_mem_region(chip->ba1_addr, CS4281_BA1_SIZE, "CS4281 BA1")) == NULL) {
- snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba1_addr, chip->ba1_addr + CS4281_BA1_SIZE - 1);
- snd_cs4281_free(chip);
- return -ENOMEM;
+ if ((err = pci_request_regions(pci, "CS4281")) < 0) {
+ kfree(chip);
+ return err;
}
+ chip->ba0_addr = pci_resource_start(pci, 0);
+ chip->ba1_addr = pci_resource_start(pci, 1);
+
if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", (void *)chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cs4281_free(chip);
}
chip->irq = pci->irq;
- chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, CS4281_BA0_SIZE);
- chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, CS4281_BA1_SIZE);
+ chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+ chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
if (!chip->ba0 || !chip->ba1) {
snd_cs4281_free(chip);
return -ENOMEM;
static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
{
- unsigned long flags;
- cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+ cs4281_t *chip = substream->rmidi->private_data;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
chip->midcr |= BA0_MIDCR_RXE;
chip->midi_input = substream;
if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
} else {
snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
{
- unsigned long flags;
- cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+ cs4281_t *chip = substream->rmidi->private_data;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE);
chip->midi_input = NULL;
if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
}
chip->uartm &= ~CS4281_MODE_INPUT;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
{
- unsigned long flags;
- cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+ cs4281_t *chip = substream->rmidi->private_data;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
chip->uartm |= CS4281_MODE_OUTPUT;
chip->midcr |= BA0_MIDCR_TXE;
chip->midi_output = substream;
} else {
snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
{
- unsigned long flags;
- cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+ cs4281_t *chip = substream->rmidi->private_data;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE);
chip->midi_output = NULL;
if (!(chip->uartm & CS4281_MODE_INPUT)) {
snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
}
chip->uartm &= ~CS4281_MODE_OUTPUT;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
{
unsigned long flags;
- cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+ cs4281_t *chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->reg_lock, flags);
if (up) {
static void snd_cs4281_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
{
unsigned long flags;
- cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+ cs4281_t *chip = substream->rmidi->private_data;
unsigned char byte;
spin_lock_irqsave(&chip->reg_lock, flags);
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, dev_id, return IRQ_NONE);
+ cs4281_t *chip = dev_id;
unsigned int status, dma, val;
cs4281_dma_t *cdma;
c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & BA0_MIDCR_RIE) == 0)
continue;
+ spin_unlock(&chip->reg_lock);
snd_rawmidi_receive(chip->midi_input, &c, 1);
+ spin_lock(&chip->reg_lock);
}
while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
if ((chip->midcr & BA0_MIDCR_TIE) == 0)
BA0_PPRVC,
};
-#define number_of(array) (sizeof(array) / sizeof(array[0]))
-
#define CLKCR1_CKRA 0x00010000L
static int cs4281_suspend(snd_card_t *card, unsigned int state)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+ cs4281_t *chip = card->pm_private_data;
u32 ulCLK;
unsigned int i;
snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
/* remember the status registers */
- for (i = 0; i < number_of(saved_regs); i++)
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
if (saved_regs[i])
chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
static int cs4281_resume(snd_card_t *card, unsigned int state)
{
- cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+ cs4281_t *chip = card->pm_private_data;
unsigned int i;
u32 ulCLK;
snd_cs4281_chip_init(chip);
/* restore the status registers */
- for (i = 0; i < number_of(saved_regs); i++)
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
if (saved_regs[i])
snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);