dma-mapping: replace all DMA_32BIT_MASK macro with DMA_BIT_MASK(32)
[safe/jmp/linux-2.6] / sound / pci / intel8x0.c
index 47485af..5764881 100644 (file)
@@ -59,6 +59,12 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
                "{SiS,SI7012},"
                "{NVidia,nForce Audio},"
                "{NVidia,nForce2 Audio},"
+               "{NVidia,nForce3 Audio},"
+               "{NVidia,MCP04},"
+               "{NVidia,MCP501},"
+               "{NVidia,CK804},"
+               "{NVidia,CK8},"
+               "{NVidia,CK8S},"
                "{AMD,AMD768},"
                "{AMD,AMD8111},"
                "{ALI,M5455}}");
@@ -77,7 +83,7 @@ MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
 module_param(ac97_clock, int, 0444);
-MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
+MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = whitelist + auto-detect, 1 = force autodetect).");
 module_param(ac97_quirk, charp, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 module_param(buggy_semaphore, bool, 0444);
@@ -611,7 +617,7 @@ static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip)
        int time = 100;
        if (chip->buggy_semaphore)
                return 0; /* just ignore ... */
-       while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
+       while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
                udelay(1);
        if (! time && ! chip->in_ac97_init)
                snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n");
@@ -683,7 +689,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich
                        bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */
                                                     ichdev->fragsize >> ichdev->pos_shift);
 #if 0
-                       printk("bdbar[%i] = 0x%x [0x%x]\n",
+                       printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n",
                               idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
 #endif
                }
@@ -695,8 +701,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich
        ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags;
        ichdev->position = 0;
 #if 0
-       printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n",
-                       ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1);
+       printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, "
+              "period_size1 = 0x%x\n",
+              ichdev->lvi_frag, ichdev->frags, ichdev->fragsize,
+              ichdev->fragsize1);
 #endif
        /* clear interrupts */
        iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
@@ -762,7 +770,8 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich
                ichdev->lvi_frag %= ichdev->frags;
                ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
 #if 0
-       printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",
+       printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, "
+              "all = 0x%x, 0x%x\n",
               ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
               ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
               inl(port + 4), inb(port + ICH_REG_OFF_CR));
@@ -1957,6 +1966,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
        },
        {
                .subvendor = 0x10cf,
+               .subdevice = 0x127d,
+               .name = "Fujitsu Lifebook P7010",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .subvendor = 0x10cf,
                .subdevice = 0x127e,
                .name = "Fujitsu Lifebook C1211D",
                .type = AC97_TUNE_HP_ONLY
@@ -2132,8 +2147,8 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
                                snd_intel8x0_codec_read_test(chip, codecs);
                                chip->ac97_sdin[codecs] =
                                        igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK;
-                               snd_assert(chip->ac97_sdin[codecs] < 3,
-                                          chip->ac97_sdin[codecs] = 0);
+                               if (snd_BUG_ON(chip->ac97_sdin[codecs] >= 3))
+                                       chip->ac97_sdin[codecs] = 0;
                        } else
                                chip->ac97_sdin[codecs] = i;
                        codecs++;
@@ -2275,23 +2290,23 @@ static void do_ali_reset(struct intel8x0 *chip)
        iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
 }
 
-static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
-{
-       unsigned long end_time;
-       unsigned int cnt, status, nstatus;
-       
-       /* put logic to right state */
-       /* first clear status bits */
-       status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
-       if (chip->device_type == DEVICE_NFORCE)
-               status |= ICH_NVSPINT;
-       cnt = igetdword(chip, ICHREG(GLOB_STA));
-       iputdword(chip, ICHREG(GLOB_STA), cnt & status);
+#ifdef CONFIG_SND_AC97_POWER_SAVE
+static struct snd_pci_quirk ich_chip_reset_mode[] = {
+       SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1),
+       { } /* end */
+};
 
+static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip)
+{
+       unsigned int cnt;
        /* ACLink on, 2 channels */
+
+       if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
+               return -EIO;
+
        cnt = igetdword(chip, ICHREG(GLOB_CNT));
        cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
-#ifdef CONFIG_SND_AC97_POWER_SAVE
+
        /* do cold reset - the full ac97 powerdown may leave the controller
         * in a warm state but actually it cannot communicate with the codec.
         */
@@ -2300,22 +2315,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
        udelay(10);
        iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD);
        msleep(1);
+       return 0;
+}
+#define snd_intel8x0_ich_chip_can_cold_reset(chip) \
+       (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode))
 #else
+#define snd_intel8x0_ich_chip_cold_reset(chip) 0
+#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0)
+#endif
+
+static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip)
+{
+       unsigned long end_time;
+       unsigned int cnt;
+       /* ACLink on, 2 channels */
+       cnt = igetdword(chip, ICHREG(GLOB_CNT));
+       cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);
        /* finish cold or do warm reset */
        cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
        iputdword(chip, ICHREG(GLOB_CNT), cnt);
        end_time = (jiffies + (HZ / 4)) + 1;
        do {
                if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
-                       goto __ok;
+                       return 0;
                schedule_timeout_uninterruptible(1);
        } while (time_after_eq(end_time, jiffies));
        snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
                   igetdword(chip, ICHREG(GLOB_CNT)));
        return -EIO;
+}
+
+static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
+{
+       unsigned long end_time;
+       unsigned int status, nstatus;
+       unsigned int cnt;
+       int err;
+
+       /* put logic to right state */
+       /* first clear status bits */
+       status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT;
+       if (chip->device_type == DEVICE_NFORCE)
+               status |= ICH_NVSPINT;
+       cnt = igetdword(chip, ICHREG(GLOB_STA));
+       iputdword(chip, ICHREG(GLOB_STA), cnt & status);
+
+       if (snd_intel8x0_ich_chip_can_cold_reset(chip))
+               err = snd_intel8x0_ich_chip_cold_reset(chip);
+       else
+               err = snd_intel8x0_ich_chip_reset(chip);
+       if (err < 0)
+               return err;
 
-      __ok:
-#endif
        if (probing) {
                /* wait for any codec ready status.
                 * Once it becomes ready it should remain ready
@@ -2468,7 +2519,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
                pci_write_config_dword(chip->pci, 0x4c, val);
        }
        /* --- */
-       synchronize_irq(chip->irq);
+
       __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
@@ -2517,7 +2568,6 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state)
                chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
 
        if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
                free_irq(chip->irq, chip);
                chip->irq = -1;
        }
@@ -2687,6 +2737,29 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
        snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
 }
 
+static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
+       SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
+       SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
+       SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000),
+       SND_PCI_QUIRK(0x1028, 0x01ad, "AD1981B", 48000),
+       SND_PCI_QUIRK(0x1043, 0x80f3, "AD1985", 48000),
+       { }     /* terminator */
+};
+
+static int __devinit intel8x0_in_clock_list(struct intel8x0 *chip)
+{
+       struct pci_dev *pci = chip->pci;
+       const struct snd_pci_quirk *wl;
+
+       wl = snd_pci_quirk_lookup(pci, intel8x0_clock_list);
+       if (!wl)
+               return 0;
+       printk(KERN_INFO "intel8x0: white list rate for %04x:%04x is %i\n",
+              pci->subsystem_vendor, pci->subsystem_device, wl->value);
+       chip->ac97_bus->clock = wl->value;
+       return 1;
+}
+
 #ifdef CONFIG_PROC_FS
 static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
                                   struct snd_info_buffer *buffer)
@@ -3024,9 +3097,9 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
        int err;
        struct shortname_table *name;
 
-       card = snd_card_new(index, id, THIS_MODULE, 0);
-       if (card == NULL)
-               return -ENOMEM;
+       err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+       if (err < 0)
+               return err;
 
        if (spdif_aclink < 0)
                spdif_aclink = check_default_spdif_aclink(pci);
@@ -3082,8 +3155,14 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                 "%s with %s at irq %i", card->shortname,
                 snd_ac97_get_short_name(chip->ac97[0]), chip->irq);
 
-       if (! ac97_clock)
-               intel8x0_measure_ac97_clock(chip);
+       if (ac97_clock == 0 || ac97_clock == 1) {
+               if (ac97_clock == 0) {
+                       if (intel8x0_in_clock_list(chip) == 0)
+                               intel8x0_measure_ac97_clock(chip);
+               } else {
+                       intel8x0_measure_ac97_clock(chip);
+               }
+       }
 
        if ((err = snd_card_register(card)) < 0) {
                snd_card_free(card);