]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'topic/sscape-fix' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Mon, 23 Mar 2009 23:36:21 +0000 (00:36 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 23 Mar 2009 23:36:21 +0000 (00:36 +0100)
sound/isa/Kconfig
sound/isa/sscape.c
sound/isa/wss/wss_lib.c

index 2df20e403f247098e3d8bb3867b220099638eaa1..c5c9a9218ff6ef3c209c7554c2c788eb3b516de2 100644 (file)
@@ -368,14 +368,17 @@ config SND_SGALAXY
          will be called snd-sgalaxy.
 
 config SND_SSCAPE
-       tristate "Ensoniq SoundScape PnP driver"
+       tristate "Ensoniq SoundScape driver"
        select SND_HWDEP
        select SND_MPU401_UART
        select SND_WSS_LIB
        help
-         Say Y here to include support for Ensoniq SoundScape PnP
+         Say Y here to include support for Ensoniq SoundScape 
          soundcards.
 
+         The PCM audio is supported on SoundScape Classic, Elite, PnP
+         and VIVO cards. The MIDI support is very experimental.
+
          To compile this driver as a module, choose M here: the module
          will be called snd-sscape.
 
index 4025fb558c5005d1b5143d8b3f41f679e6f54184..66187122377c544cbc2059a9e8c0ecd9fa5a594a 100644 (file)
@@ -89,9 +89,6 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
 #endif
 
 
-#define MPU401_IO(i)     ((i) + 0)
-#define MIDI_DATA_IO(i)  ((i) + 0)
-#define MIDI_CTRL_IO(i)  ((i) + 1)
 #define HOST_CTRL_IO(i)  ((i) + 2)
 #define HOST_DATA_IO(i)  ((i) + 3)
 #define ODIE_ADDR_IO(i)  ((i) + 4)
@@ -129,9 +126,6 @@ enum GA_REG {
 #define DMA_8BIT  0x80
 
 
-#define AD1845_FREQ_SEL_MSB    0x16
-#define AD1845_FREQ_SEL_LSB    0x17
-
 enum card_type {
        SSCAPE,
        SSCAPE_PNP,
@@ -141,8 +135,6 @@ enum card_type {
 struct soundscape {
        spinlock_t lock;
        unsigned io_base;
-       unsigned wss_base;
-       int codec_type;
        int ic_type;
        enum card_type type;
        struct resource *io_res;
@@ -330,7 +322,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
  */
 static inline int verify_mpu401(const struct snd_mpu401 * mpu)
 {
-       return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80);
+       return ((inb(MPU401C(mpu)) & 0xc0) == 0x80);
 }
 
 /*
@@ -338,7 +330,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu)
  */
 static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
 {
-       outb(0, MIDI_DATA_IO(mpu->port));
+       outb(0, MPU401D(mpu));
 }
 
 /*
@@ -396,20 +388,20 @@ static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned ti
  */
 static int obp_startup_ack(struct soundscape *s, unsigned timeout)
 {
-       while (timeout != 0) {
+       unsigned long end_time = jiffies + msecs_to_jiffies(timeout);
+
+       do {
                unsigned long flags;
                unsigned char x;
 
-               schedule_timeout_uninterruptible(1);
-
                spin_lock_irqsave(&s->lock, flags);
                x = inb(HOST_DATA_IO(s->io_base));
                spin_unlock_irqrestore(&s->lock, flags);
                if ((x & 0xfe) == 0xfe)
                        return 1;
 
-               --timeout;
-       } /* while */
+               msleep(10);
+       } while (time_before(jiffies, end_time));
 
        return 0;
 }
@@ -423,20 +415,20 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout)
  */
 static int host_startup_ack(struct soundscape *s, unsigned timeout)
 {
-       while (timeout != 0) {
+       unsigned long end_time = jiffies + msecs_to_jiffies(timeout);
+
+       do {
                unsigned long flags;
                unsigned char x;
 
-               schedule_timeout_uninterruptible(1);
-
                spin_lock_irqsave(&s->lock, flags);
                x = inb(HOST_DATA_IO(s->io_base));
                spin_unlock_irqrestore(&s->lock, flags);
                if (x == 0xfe)
                        return 1;
 
-               --timeout;
-       } /* while */
+               msleep(10);
+       } while (time_before(jiffies, end_time));
 
        return 0;
 }
@@ -532,10 +524,10 @@ static int upload_dma_data(struct soundscape *s,
         * give it 5 seconds (max) ...
         */
        ret = 0;
-       if (!obp_startup_ack(s, 5)) {
+       if (!obp_startup_ack(s, 5000)) {
                snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
                ret = -EAGAIN;
-       } else if (!host_startup_ack(s, 5)) {
+       } else if (!host_startup_ack(s, 5000)) {
                snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
                ret = -EAGAIN;
        }
@@ -732,13 +724,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl,
        unsigned long flags;
 
        spin_lock_irqsave(&s->lock, flags);
-       set_host_mode_unsafe(s->io_base);
-
-       if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) {
-               uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100);
-       }
-
-       set_midi_mode_unsafe(s->io_base);
+       uctl->value.integer.value[0] = s->midi_vol;
        spin_unlock_irqrestore(&s->lock, flags);
        return 0;
 }
@@ -773,6 +759,7 @@ static int sscape_midi_put(struct snd_kcontrol *kctl,
        change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
                  && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100)
                  && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100));
+       s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127;
       __skip_change:
 
        /*
@@ -815,12 +802,11 @@ static unsigned __devinit get_irq_config(int irq)
  * Perform certain arcane port-checks to see whether there
  * is a SoundScape board lurking behind the given ports.
  */
-static int __devinit detect_sscape(struct soundscape *s)
+static int __devinit detect_sscape(struct soundscape *s, long wss_io)
 {
        unsigned long flags;
        unsigned d;
        int retval = 0;
-       int codec = s->wss_base;
 
        spin_lock_irqsave(&s->lock, flags);
 
@@ -836,13 +822,11 @@ static int __devinit detect_sscape(struct soundscape *s)
        if ((d & 0x80) != 0)
                goto _done;
 
-       if (d == 0) {
-               s->codec_type = 1;
+       if (d == 0)
                s->ic_type = IC_ODIE;
-       } else if ((d & 0x60) != 0) {
-               s->codec_type = 2;
+       else if ((d & 0x60) != 0)
                s->ic_type = IC_OPUS;
-       else
+       else
                goto _done;
 
        outb(0xfa, ODIE_ADDR_IO(s->io_base));
@@ -862,10 +846,10 @@ static int __devinit detect_sscape(struct soundscape *s)
        sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
 
        if (s->type == SSCAPE_VIVO)
-               codec += 4;
+               wss_io += 4;
        /* wait for WSS codec */
        for (d = 0; d < 500; d++) {
-               if ((inb(codec) & 0x80) == 0)
+               if ((inb(wss_io) & 0x80) == 0)
                        break;
                spin_unlock_irqrestore(&s->lock, flags);
                msleep(1);
@@ -954,82 +938,6 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l
 }
 
 
-/*
- * Override for the CS4231 playback format function.
- * The AD1845 has much simpler format and rate selection.
- */
-static void ad1845_playback_format(struct snd_wss *chip,
-                                  struct snd_pcm_hw_params *params,
-                                  unsigned char format)
-{
-       unsigned long flags;
-       unsigned rate = params_rate(params);
-
-       /*
-        * The AD1845 can't handle sample frequencies
-        * outside of 4 kHZ to 50 kHZ
-        */
-       if (rate > 50000)
-               rate = 50000;
-       else if (rate < 4000)
-               rate = 4000;
-
-       spin_lock_irqsave(&chip->reg_lock, flags);
-
-       /*
-        * Program the AD1845 correctly for the playback stream.
-        * Note that we do NOT need to toggle the MCE bit because
-        * the PLAYBACK_ENABLE bit of the Interface Configuration
-        * register is set.
-        * 
-        * NOTE: We seem to need to write to the MSB before the LSB
-        *       to get the correct sample frequency.
-        */
-       snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
-       snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
-       snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
-
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-/*
- * Override for the CS4231 capture format function. 
- * The AD1845 has much simpler format and rate selection.
- */
-static void ad1845_capture_format(struct snd_wss *chip,
-                                 struct snd_pcm_hw_params *params,
-                                 unsigned char format)
-{
-       unsigned long flags;
-       unsigned rate = params_rate(params);
-
-       /*
-        * The AD1845 can't handle sample frequencies 
-        * outside of 4 kHZ to 50 kHZ
-        */
-       if (rate > 50000)
-               rate = 50000;
-       else if (rate < 4000)
-               rate = 4000;
-
-       spin_lock_irqsave(&chip->reg_lock, flags);
-
-       /*
-        * Program the AD1845 correctly for the playback stream.
-        * Note that we do NOT need to toggle the MCE bit because
-        * the CAPTURE_ENABLE bit of the Interface Configuration
-        * register is set.
-        *
-        * NOTE: We seem to need to write to the MSB before the LSB
-        *       to get the correct sample frequency.
-        */
-       snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
-       snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
-       snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
-
-       spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
 /*
  * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
  * is very much like a CS4231, with a few extra bits. We will
@@ -1055,11 +963,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
                unsigned long flags;
                struct snd_pcm *pcm;
 
-#define AD1845_FREQ_SEL_ENABLE  0x08
-
-#define AD1845_PWR_DOWN_CTRL   0x1b
-#define AD1845_CRYS_CLOCK_SEL  0x1d
-
 /*
  * It turns out that the PLAYBACK_ENABLE bit is set
  * by the lowlevel driver ...
@@ -1074,7 +977,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
  */
 
                if (sscape->type != SSCAPE_VIVO) {
-                       int val;
                        /*
                         * The input clock frequency on the SoundScape must
                         * be 14.31818 MHz, because we must set this register
@@ -1082,22 +984,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
                         */
                        snd_wss_mce_up(chip);
                        spin_lock_irqsave(&chip->reg_lock, flags);
-                       snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
+                       snd_wss_out(chip, AD1845_CLOCK, 0x20);
                        spin_unlock_irqrestore(&chip->reg_lock, flags);
                        snd_wss_mce_down(chip);
 
-                       /*
-                        * More custom configuration:
-                        * a) select "mode 2" and provide a current drive of 8mA
-                        * b) enable frequency selection (for capture/playback)
-                        */
-                       spin_lock_irqsave(&chip->reg_lock, flags);
-                       snd_wss_out(chip, CS4231_MISC_INFO,
-                                   CS4231_MODE2 | 0x10);
-                       val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL);
-                       snd_wss_out(chip, AD1845_PWR_DOWN_CTRL,
-                                   val | AD1845_FREQ_SEL_ENABLE);
-                       spin_unlock_irqrestore(&chip->reg_lock, flags);
                }
 
                err = snd_wss_pcm(chip, 0, &pcm);
@@ -1113,11 +1003,13 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
                                            "for AD1845 chip\n");
                        goto _error;
                }
-               err = snd_wss_timer(chip, 0, NULL);
-               if (err < 0) {
-                       snd_printk(KERN_ERR "sscape: No timer device "
-                                           "for AD1845 chip\n");
-                       goto _error;
+               if (chip->hardware != WSS_HW_AD1848) {
+                       err = snd_wss_timer(chip, 0, NULL);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR "sscape: No timer device "
+                                                   "for AD1845 chip\n");
+                               goto _error;
+                       }
                }
 
                if (sscape->type != SSCAPE_VIVO) {
@@ -1128,8 +1020,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
                                                    "MIDI mixer control\n");
                                goto _error;
                        }
-                       chip->set_playback_format = ad1845_playback_format;
-                       chip->set_capture_format = ad1845_capture_format;
                }
 
                strcpy(card->driver, "SoundScape");
@@ -1157,7 +1047,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
        unsigned dma_cfg;
        unsigned irq_cfg;
        unsigned mpu_irq_cfg;
-       unsigned xport;
        struct resource *io_res;
        struct resource *wss_res;
        unsigned long flags;
@@ -1177,15 +1066,15 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
                printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
                return -ENXIO;
        }
-       xport = port[dev];
 
        /*
         * Grab IO ports that we will need to probe so that we
         * can detect and control this hardware ...
         */
-       io_res = request_region(xport, 8, "SoundScape");
+       io_res = request_region(port[dev], 8, "SoundScape");
        if (!io_res) {
-               snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport);
+               snd_printk(KERN_ERR
+                          "sscape: can't grab port 0x%lx\n", port[dev]);
                return -EBUSY;
        }
        wss_res = NULL;
@@ -1212,10 +1101,9 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
        spin_lock_init(&sscape->fwlock);
        sscape->io_res = io_res;
        sscape->wss_res = wss_res;
-       sscape->io_base = xport;
-       sscape->wss_base = wss_port[dev];
+       sscape->io_base = port[dev];
 
-       if (!detect_sscape(sscape)) {
+       if (!detect_sscape(sscape, wss_port[dev])) {
                printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
                err = -ENODEV;
                goto _release_dma;
@@ -1288,12 +1176,11 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
        }
 #define MIDI_DEVNUM  0
        if (sscape->type != SSCAPE_VIVO) {
-               err = create_mpu401(card, MIDI_DEVNUM,
-                                   MPU401_IO(xport), mpu_irq[dev]);
+               err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]);
                if (err < 0) {
                        printk(KERN_ERR "sscape: Failed to create "
-                                       "MPU-401 device at 0x%x\n",
-                                       MPU401_IO(xport));
+                                       "MPU-401 device at 0x%lx\n",
+                                       port[dev]);
                        goto _release_dma;
                }
 
index ac27832b2c6f8e9714f05d5fa801ebced963586c..5d2ba1b749abef59839210b177944cd3c9a8a24c 100644 (file)
@@ -181,25 +181,6 @@ static void snd_wss_wait(struct snd_wss *chip)
                udelay(100);
 }
 
-static void snd_wss_outm(struct snd_wss *chip, unsigned char reg,
-                           unsigned char mask, unsigned char value)
-{
-       unsigned char tmp = (chip->image[reg] & mask) | value;
-
-       snd_wss_wait(chip);
-#ifdef CONFIG_SND_DEBUG
-       if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-               snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
-       chip->image[reg] = tmp;
-       if (!chip->calibrate_mute) {
-               wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
-               wmb();
-               wss_outb(chip, CS4231P(REG), tmp);
-               mb();
-       }
-}
-
 static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
                         unsigned char value)
 {
@@ -597,7 +578,15 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
                             chip->image[CS4231_RIGHT_INPUT]);
                snd_wss_dout(chip, CS4231_LOOPBACK,
                             chip->image[CS4231_LOOPBACK]);
+       } else {
+               snd_wss_dout(chip, CS4231_LEFT_INPUT,
+                            0);
+               snd_wss_dout(chip, CS4231_RIGHT_INPUT,
+                            0);
+               snd_wss_dout(chip, CS4231_LOOPBACK,
+                            0xfd);
        }
+
        snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
                     mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
        snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
@@ -640,7 +629,6 @@ static void snd_wss_playback_format(struct snd_wss *chip,
        int full_calib = 1;
 
        mutex_lock(&chip->mce_mutex);
-       snd_wss_calibrate_mute(chip, 1);
        if (chip->hardware == WSS_HW_CS4231A ||
            (chip->hardware & WSS_HW_CS4232_MASK)) {
                spin_lock_irqsave(&chip->reg_lock, flags);
@@ -656,6 +644,24 @@ static void snd_wss_playback_format(struct snd_wss *chip,
                        full_calib = 0;
                }
                spin_unlock_irqrestore(&chip->reg_lock, flags);
+       } else if (chip->hardware == WSS_HW_AD1845) {
+               unsigned rate = params_rate(params);
+
+               /*
+                * Program the AD1845 correctly for the playback stream.
+                * Note that we do NOT need to toggle the MCE bit because
+                * the PLAYBACK_ENABLE bit of the Interface Configuration
+                * register is set.
+                *
+                * NOTE: We seem to need to write to the MSB before the LSB
+                *       to get the correct sample frequency.
+                */
+               spin_lock_irqsave(&chip->reg_lock, flags);
+               snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0));
+               snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
+               snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
+               full_calib = 0;
+               spin_unlock_irqrestore(&chip->reg_lock, flags);
        }
        if (full_calib) {
                snd_wss_mce_up(chip);
@@ -673,7 +679,6 @@ static void snd_wss_playback_format(struct snd_wss *chip,
                        udelay(100);    /* this seems to help */
                snd_wss_mce_down(chip);
        }
-       snd_wss_calibrate_mute(chip, 0);
        mutex_unlock(&chip->mce_mutex);
 }
 
@@ -685,7 +690,6 @@ static void snd_wss_capture_format(struct snd_wss *chip,
        int full_calib = 1;
 
        mutex_lock(&chip->mce_mutex);
-       snd_wss_calibrate_mute(chip, 1);
        if (chip->hardware == WSS_HW_CS4231A ||
            (chip->hardware & WSS_HW_CS4232_MASK)) {
                spin_lock_irqsave(&chip->reg_lock, flags);
@@ -700,6 +704,24 @@ static void snd_wss_capture_format(struct snd_wss *chip,
                        full_calib = 0;
                }
                spin_unlock_irqrestore(&chip->reg_lock, flags);
+       } else if (chip->hardware == WSS_HW_AD1845) {
+               unsigned rate = params_rate(params);
+
+               /*
+                * Program the AD1845 correctly for the capture stream.
+                * Note that we do NOT need to toggle the MCE bit because
+                * the PLAYBACK_ENABLE bit of the Interface Configuration
+                * register is set.
+                *
+                * NOTE: We seem to need to write to the MSB before the LSB
+                *       to get the correct sample frequency.
+                */
+               spin_lock_irqsave(&chip->reg_lock, flags);
+               snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0));
+               snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
+               snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
+               full_calib = 0;
+               spin_unlock_irqrestore(&chip->reg_lock, flags);
        }
        if (full_calib) {
                snd_wss_mce_up(chip);
@@ -724,7 +746,6 @@ static void snd_wss_capture_format(struct snd_wss *chip,
                spin_unlock_irqrestore(&chip->reg_lock, flags);
                snd_wss_mce_down(chip);
        }
-       snd_wss_calibrate_mute(chip, 0);
        mutex_unlock(&chip->mce_mutex);
 }
 
@@ -781,6 +802,7 @@ static void snd_wss_init(struct snd_wss *chip)
 {
        unsigned long flags;
 
+       snd_wss_calibrate_mute(chip, 1);
        snd_wss_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
@@ -804,6 +826,8 @@ static void snd_wss_init(struct snd_wss *chip)
 
        snd_wss_mce_up(chip);
        spin_lock_irqsave(&chip->reg_lock, flags);
+       chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB;
+       snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
        snd_wss_out(chip,
                    CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -837,6 +861,7 @@ static void snd_wss_init(struct snd_wss *chip)
                            chip->image[CS4231_REC_FORMAT]);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
        snd_wss_mce_down(chip);
+       snd_wss_calibrate_mute(chip, 0);
 
 #ifdef SNDRV_DEBUG_MCE
        snd_printk(KERN_DEBUG "init: (5)\n");
@@ -895,8 +920,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
                mutex_unlock(&chip->open_mutex);
                return;
        }
-       snd_wss_calibrate_mute(chip, 1);
-
        /* disable IRQ */
        spin_lock_irqsave(&chip->reg_lock, flags);
        if (!(chip->hardware & WSS_HW_AD1848_MASK))
@@ -929,8 +952,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
        spin_unlock_irqrestore(&chip->reg_lock, flags);
 
-       snd_wss_calibrate_mute(chip, 0);
-
        chip->mode = 0;
        mutex_unlock(&chip->open_mutex);
 }
@@ -1123,7 +1144,7 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
        if (chip->hardware & WSS_HW_AD1848_MASK)
                wss_outb(chip, CS4231P(STATUS), 0);
        else
-               snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
+               snd_wss_out(chip, CS4231_IRQ_STATUS, status);
        spin_unlock(&chip->reg_lock);
        return IRQ_HANDLED;
 }
@@ -1325,6 +1346,10 @@ static int snd_wss_probe(struct snd_wss *chip)
                chip->image[CS4231_ALT_FEATURE_2] =
                        chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
        }
+       /* enable fine grained frequency selection */
+       if (chip->hardware == WSS_HW_AD1845)
+               chip->image[AD1845_PWR_DOWN] = 8;
+
        ptr = (unsigned char *) &chip->image;
        regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
        snd_wss_mce_down(chip);