#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
+#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
#include <sound/ac97_codec.h>
#include <sound/opl3.h>
-#define SNDRV_GET_ID
#include <sound/initval.h>
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 */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
static int dual_codec[SNDRV_CARDS]; /* dual codec */
-MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for CS4281 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 CS4281 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 CS4281 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_PARM(dual_codec, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(dual_codec, bool, NULL, 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;
struct snd_cs4281 {
int irq;
- unsigned long ba0; /* virtual (accessible) address */
- unsigned long ba1; /* virtual (accessible) address */
+ void __iomem *ba0; /* virtual (accessible) address */
+ void __iomem *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);
}
static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data,
- struct file *file, char *buf, long count)
+ struct file *file, char __user *buf,
+ 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 (file->f_pos + size > CS4281_BA0_SIZE)
- size = (long)CS4281_BA0_SIZE - file->f_pos;
+ if (pos + size > CS4281_BA0_SIZE)
+ size = (long)CS4281_BA0_SIZE - pos;
if (size > 0) {
- if (copy_to_user_fromio(buf, chip->ba0 + file->f_pos, size))
+ if (copy_to_user_fromio(buf, chip->ba0 + pos, size))
return -EFAULT;
- file->f_pos += size;
}
return size;
}
static long snd_cs4281_BA1_read(snd_info_entry_t *entry, void *file_private_data,
- struct file *file, char *buf, long count)
+ struct file *file, char __user *buf,
+ 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 (file->f_pos + size > CS4281_BA1_SIZE)
- size = (long)CS4281_BA1_SIZE - file->f_pos;
+ if (pos + size > CS4281_BA1_SIZE)
+ size = (long)CS4281_BA1_SIZE - pos;
if (size > 0) {
- if (copy_to_user_fromio(buf, chip->ba1 + file->f_pos, size))
+ if (copy_to_user_fromio(buf, chip->ba1 + pos, size))
return -EFAULT;
- file->f_pos += size;
}
return 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->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);
+ if (chip->ba0)
+ iounmap(chip->ba0);
+ if (chip->ba1)
+ iounmap(chip->ba1);
+ pci_release_regions(chip->pci);
+ pci_disable_device(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);
}
static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */
#ifdef CONFIG_PM
-static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state);
+static int cs4281_suspend(snd_card_t *card, unsigned int state);
+static int cs4281_resume(snd_card_t *card, unsigned int state);
#endif
static int __devinit snd_cs4281_create(snd_card_t * card,
*rchip = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = snd_magic_kcalloc(cs4281_t, 0, GFP_KERNEL);
- if (chip == NULL)
+ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
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);
+ pci_disable_device(pci);
+ 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 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+ chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
if (!chip->ba0 || !chip->ba1) {
snd_cs4281_free(chip);
return -ENOMEM;
return tmp;
}
- snd_cs4281_proc_init(chip);
-
-#ifdef CONFIG_PM
- card->set_power_state = snd_cs4281_set_power_state;
- card->power_state_private_data = chip;
-#endif
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_cs4281_free(chip);
return err;
}
+ snd_cs4281_proc_init(chip);
+
+ snd_card_set_pm_callback(card, cs4281_suspend, cs4281_resume, chip);
+
snd_card_set_dev(card, &pci->dev);
*rchip = chip;
{
unsigned int tmp;
int timeout;
+ int retry_count = 2;
+ __retry:
tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
if (tmp != BA0_CFLR_DEFAULT) {
snd_cs4281_pokeBA0(chip, BA0_CFLR, BA0_CFLR_DEFAULT);
snd_cs4281_delay_long();
} while (timeout-- > 0);
+ if (--retry_count > 0)
+ goto __retry;
snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n");
return -EIO;
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)
}
+/*
+ * OPL3 command
+ */
+static void snd_cs4281_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
+{
+ unsigned long flags;
+ cs4281_t *chip = opl3->private_data;
+ void __iomem *port;
+
+ if (cmd & OPL3_RIGHT)
+ port = chip->ba0 + BA0_B1AP; /* right port */
+ else
+ port = chip->ba0 + BA0_B0AP; /* left port */
+
+ spin_lock_irqsave(&opl3->reg_lock, flags);
+
+ writel((unsigned int)cmd, port);
+ udelay(10);
+
+ writel((unsigned int)val, port + 4);
+ udelay(30);
+
+ spin_unlock_irqrestore(&opl3->reg_lock, flags);
+}
+
static int __devinit snd_cs4281_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
snd_card_free(card);
return err;
}
- if ((err = snd_opl3_create(card,
- (chip->ba0 + BA0_B0AP) >> 2,
- (chip->ba0 + BA0_B1AP) >> 2,
- OPL3_HW_OPL3_CS4281, 1, &opl3)) < 0) {
+ if ((err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3)) < 0) {
snd_card_free(card);
return err;
}
+ opl3->private_data = chip;
+ opl3->command = snd_cs4281_opl3_command;
+ snd_opl3_init(opl3);
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
snd_card_free(card);
return err;
return err;
}
- pci_set_drvdata(pci, chip);
+ pci_set_drvdata(pci, card);
dev++;
return 0;
}
static void __devexit snd_cs4281_remove(struct pci_dev *pci)
{
- cs4281_t *chip = pci_get_drvdata(pci);
- snd_card_free(chip->card);
+ snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
}
BA0_PPRVC,
};
-#define number_of(array) (sizeof(array) / sizeof(array[0]))
-
#define CLKCR1_CKRA 0x00010000L
-static void cs4281_suspend(cs4281_t *chip)
+static int cs4281_suspend(snd_card_t *card, unsigned int state)
{
- snd_card_t *card = chip->card;
+ cs4281_t *chip = card->pm_private_data;
u32 ulCLK;
unsigned int i;
- if (card->power_state == SNDRV_CTL_POWER_D3hot)
- return;
-
snd_pcm_suspend_all(chip->pcm);
+ if (chip->ac97)
+ snd_ac97_suspend(chip->ac97);
+ if (chip->ac97_secondary)
+ snd_ac97_suspend(chip->ac97_secondary);
+
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK |= CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
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]);
ulCLK &= ~CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ pci_disable_device(chip->pci);
+ return 0;
}
-static void cs4281_resume(cs4281_t *chip)
+static int cs4281_resume(snd_card_t *card, unsigned int state)
{
- snd_card_t *card = chip->card;
+ cs4281_t *chip = card->pm_private_data;
unsigned int i;
u32 ulCLK;
- if (card->power_state == SNDRV_CTL_POWER_D0)
- return;
-
pci_enable_device(chip->pci);
+ pci_set_master(chip->pci);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK |= CLKCR1_CKRA;
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]);
ulCLK &= ~CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-}
-
-static int snd_cs4281_suspend(struct pci_dev *dev, u32 state)
-{
- cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return -ENXIO);
- cs4281_suspend(chip);
- return 0;
-}
-static int snd_cs4281_resume(struct pci_dev *dev)
-{
- cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return -ENXIO);
- cs4281_resume(chip);
return 0;
}
-
-/* callback */
-static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state)
-{
- cs4281_t *chip = snd_magic_cast(cs4281_t, card->power_state_private_data, return -ENXIO);
- switch (power_state) {
- case SNDRV_CTL_POWER_D0:
- case SNDRV_CTL_POWER_D1:
- case SNDRV_CTL_POWER_D2:
- cs4281_resume(chip);
- break;
- case SNDRV_CTL_POWER_D3hot:
- case SNDRV_CTL_POWER_D3cold:
- cs4281_suspend(chip);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
#endif /* CONFIG_PM */
static struct pci_driver driver = {
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
.remove = __devexit_p(snd_cs4281_remove),
-#ifdef CONFIG_PM
- .suspend = snd_cs4281_suspend,
- .resume = snd_cs4281_resume,
-#endif
+ SND_PCI_PM_CALLBACKS
};
static int __init alsa_card_cs4281_init(void)
{
- int err;
-
- if ((err = pci_module_init(&driver)) < 0) {
-#ifdef MODULE
- printk(KERN_ERR "CS4281 soundcard not found or device busy\n");
-#endif
- return err;
- }
- return 0;
+ return pci_module_init(&driver);
}
static void __exit alsa_card_cs4281_exit(void)
module_init(alsa_card_cs4281_init)
module_exit(alsa_card_cs4281_exit)
-
-#ifndef MODULE
-
-/* format is: snd-cs4281=enable,index,id */
-
-static int __init alsa_card_cs4281_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);
- nr_dev++;
- return 1;
-}
-
-__setup("snd-cs4281=", alsa_card_cs4281_setup);
-
-#endif /* ifndef MODULE */