Merge branch 'fix/hda' into for-linus
[safe/jmp/linux-2.6] / sound / pci / fm801.c
index bdfda19..60cdb9e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  The driver for the ForteMedia FM801 based soundcards
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  *
  *  Support FM only card by Andy Shevchenko <andy@smile.org.ua>
  *
@@ -20,7 +20,6 @@
  *
  */
 
-#include <sound/driver.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -42,7 +41,7 @@
 #define TEA575X_RADIO 1
 #endif
 
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("ForteMedia FM801");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801},"
@@ -520,7 +519,7 @@ static snd_pcm_uframes_t snd_fm801_capture_pointer(struct snd_pcm_substream *sub
        return bytes_to_frames(substream->runtime, ptr);
 }
 
-static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id)
 {
        struct fm801 *chip = dev_id;
        unsigned short status;
@@ -561,7 +560,7 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *re
                snd_pcm_period_elapsed(chip->capture_substream);
        }
        if (chip->rmidi && (status & FM801_IRQ_MPU))
-               snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+               snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
        if (status & FM801_IRQ_VOLUME)
                ;/* TODO */
 
@@ -979,6 +978,27 @@ static unsigned int snd_fm801_tea575x_64pcr_read(struct snd_tea575x *tea)
        return val;
 }
 
+static void snd_fm801_tea575x_64pcr_mute(struct snd_tea575x *tea,
+                                         unsigned int mute)
+{
+       struct fm801 *chip = tea->private_data;
+       unsigned short reg;
+
+       spin_lock_irq(&chip->reg_lock);
+
+       reg = inw(FM801_REG(chip, GPIO_CTRL));
+       if (mute)
+               /* 0xf800 (mute) */
+               reg &= ~FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
+       else
+               /* 0xf802 (unmute) */
+               reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
+       outw(reg, FM801_REG(chip, GPIO_CTRL));
+       udelay(1);
+
+       spin_unlock_irq(&chip->reg_lock);
+}
+
 static struct snd_tea575x_ops snd_fm801_tea_ops[3] = {
        {
                /* 1 = MediaForte 256-PCS */
@@ -994,6 +1014,7 @@ static struct snd_tea575x_ops snd_fm801_tea_ops[3] = {
                /* 3 = MediaForte 64-PCR */
                .write = snd_fm801_tea575x_64pcr_write,
                .read = snd_fm801_tea575x_64pcr_read,
+               .mute = snd_fm801_tea575x_64pcr_mute,
        }
 };
 #endif
@@ -1157,7 +1178,7 @@ static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol,
        return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val);
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
 
 #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
 
@@ -1264,7 +1285,6 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
 
 static int snd_fm801_chip_init(struct fm801 *chip, int resume)
 {
-       int id;
        unsigned short cmdw;
 
        if (chip->tea575x_tuner & 0x0010)
@@ -1289,13 +1309,14 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
                } else {
                        /* my card has the secondary codec */
                        /* at address #3, so the loop is inverted */
-                       for (id = 3; id > 0; id--) {
-                               if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
+                       int i;
+                       for (i = 3; i > 0; i--) {
+                               if (!wait_for_codec(chip, i, AC97_VENDOR_ID1,
                                                     msecs_to_jiffies(50))) {
                                        cmdw = inw(FM801_REG(chip, AC97_DATA));
                                        if (cmdw != 0xffff && cmdw != 0) {
                                                chip->secondary = 1;
-                                               chip->secondary_addr = id;
+                                               chip->secondary_addr = i;
                                                break;
                                        }
                                }
@@ -1369,7 +1390,6 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                                      struct fm801 ** rchip)
 {
        struct fm801 *chip;
-       unsigned char rev;
        int err;
        static struct snd_device_ops ops = {
                .dev_free =     snd_fm801_dev_free,
@@ -1395,7 +1415,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
        }
        chip->port = pci_resource_start(pci, 0);
        if ((tea575x_tuner & 0x0010) == 0) {
-               if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED,
+               if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED,
                                "FM801", chip)) {
                        snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq);
                        snd_fm801_free(chip);
@@ -1405,8 +1425,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                pci_set_master(pci);
        }
 
-       pci_read_config_byte(pci, PCI_REVISION_ID, &rev);
-       if (rev >= 0xb1)        /* FM801-AU */
+       if (pci->revision >= 0xb1)      /* FM801-AU */
                chip->multichannel = 1;
 
        snd_fm801_chip_init(chip, 0);
@@ -1449,9 +1468,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-       if (card == NULL)
-               return -ENOMEM;
+       err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+       if (err < 0)
+               return err;
        if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) {
                snd_card_free(card);
                return err;
@@ -1531,9 +1550,9 @@ static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state)
                chip->saved_regs[i] = inw(chip->port + saved_regs[i]);
        /* FIXME: tea575x suspend */
 
-       pci_set_power_state(pci, PCI_D3hot);
        pci_disable_device(pci);
        pci_save_state(pci);
+       pci_set_power_state(pci, pci_choose_state(pci, state));
        return 0;
 }
 
@@ -1543,9 +1562,14 @@ static int snd_fm801_resume(struct pci_dev *pci)
        struct fm801 *chip = card->private_data;
        int i;
 
-       pci_restore_state(pci);
-       pci_enable_device(pci);
        pci_set_power_state(pci, PCI_D0);
+       pci_restore_state(pci);
+       if (pci_enable_device(pci) < 0) {
+               printk(KERN_ERR "fm801: pci_enable_device failed, "
+                      "disabling device\n");
+               snd_card_disconnect(card);
+               return -EIO;
+       }
        pci_set_master(pci);
 
        snd_fm801_chip_init(chip, 1);