clps711xfb: convert to proc_fops
[safe/jmp/linux-2.6] / sound / isa / es18xx.c
index f7732bf..9a43baa 100644 (file)
@@ -77,7 +77,6 @@
  *   needed for ZV, so maybe the datasheet is entirely wrong here.
  */
  
-#include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/isa.h>
 
 struct snd_es18xx {
        unsigned long port;             /* port of ESS chip */
-       unsigned long mpu_port;         /* MPU-401 port of ESS chip */
-       unsigned long fm_port;          /* FM port */
        unsigned long ctrl_port;        /* Control port of ESS chip */
        struct resource *res_port;
        struct resource *res_mpu_port;
@@ -117,12 +114,9 @@ struct snd_es18xx {
        unsigned short audio2_vol;      /* volume level of audio2 */
 
        unsigned short active;          /* active channel mask */
-       unsigned int dma1_size;
-       unsigned int dma2_size;
        unsigned int dma1_shift;
        unsigned int dma2_shift;
 
-       struct snd_card *card;
        struct snd_pcm *pcm;
        struct snd_pcm_substream *playback_a_substream;
        struct snd_pcm_substream *capture_a_substream;
@@ -137,14 +131,9 @@ struct snd_es18xx {
 
        spinlock_t reg_lock;
        spinlock_t mixer_lock;
-       spinlock_t ctrl_lock;
 #ifdef CONFIG_PM
        unsigned char pm_reg;
 #endif
-};
-
-struct snd_audiodrive {
-       struct snd_es18xx *chip;
 #ifdef CONFIG_PNP
        struct pnp_dev *dev;
        struct pnp_dev *devc;
@@ -163,7 +152,7 @@ struct snd_audiodrive {
 #define ES18XX_DUPLEX_SAME 0x0010      /* Playback and record must share the same rate */
 #define ES18XX_NEW_RATE        0x0020  /* More precise rate setting */
 #define ES18XX_AUXB    0x0040  /* AuxB mixer control */
-#define ES18XX_HWV     0x0080  /* Has seperate hardware volume mixer controls*/
+#define ES18XX_HWV     0x0080  /* Has separate hardware volume mixer controls*/
 #define ES18XX_MONO    0x0100  /* Mono_in mixer control */
 #define ES18XX_I2S     0x0200  /* I2S mixer control */
 #define ES18XX_MUTEREC 0x0400  /* Record source can be muted */
@@ -360,7 +349,7 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch
 }
 
 
-static int snd_es18xx_reset(struct snd_es18xx *chip)
+static int __devinit snd_es18xx_reset(struct snd_es18xx *chip)
 {
        int i;
         outb(0x03, chip->port + 0x06);
@@ -496,8 +485,6 @@ static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip,
        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
        unsigned int count = snd_pcm_lib_period_bytes(substream);
 
-       chip->dma2_size = size;
-
         snd_es18xx_rate_set(chip, substream, DAC2);
 
         /* Transfer Count Reload */
@@ -597,8 +584,6 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
        unsigned int count = snd_pcm_lib_period_bytes(substream);
 
-       chip->dma1_size = size;
-
        snd_es18xx_reset_fifo(chip);
 
         /* Set stereo/mono */
@@ -623,7 +608,7 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
                          (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
                          (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
 
-        /* Set DMA controler */
+        /* Set DMA controller */
         snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
 
        return 0;
@@ -665,8 +650,6 @@ static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip,
        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
        unsigned int count = snd_pcm_lib_period_bytes(substream);
 
-       chip->dma1_size = size;
-
        snd_es18xx_reset_fifo(chip);
 
         /* Set stereo/mono */
@@ -689,7 +672,7 @@ static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip,
                          (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
                          (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
 
-        /* Set DMA controler */
+        /* Set DMA controller */
         snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
 
        return 0;
@@ -756,7 +739,8 @@ static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream,
 
 static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
 {
-       struct snd_es18xx *chip = dev_id;
+       struct snd_card *card = dev_id;
+       struct snd_es18xx *chip = card->private_data;
        unsigned char status;
 
        if (chip->caps & ES18XX_CONTROL) {
@@ -806,12 +790,16 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
                int split = 0;
                if (chip->caps & ES18XX_HWV) {
                        split = snd_es18xx_mixer_read(chip, 0x64) & 0x80;
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id);
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->hw_switch->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->hw_volume->id);
                }
                if (!split) {
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->master_switch->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->master_volume->id);
                }
                /* ack interrupt */
                snd_es18xx_mixer_write(chip, 0x66, 0x00);
@@ -822,17 +810,18 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
 static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream)
 {
         struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
+       unsigned int size = snd_pcm_lib_buffer_bytes(substream);
        int pos;
 
        if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
                if (!(chip->active & DAC2))
                        return 0;
-               pos = snd_dma_pointer(chip->dma2, chip->dma2_size);
+               pos = snd_dma_pointer(chip->dma2, size);
                return pos >> chip->dma2_shift;
        } else {
                if (!(chip->active & DAC1))
                        return 0;
-               pos = snd_dma_pointer(chip->dma1, chip->dma1_size);
+               pos = snd_dma_pointer(chip->dma1, size);
                return pos >> chip->dma1_shift;
        }
 }
@@ -840,11 +829,12 @@ static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *s
 static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream)
 {
         struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
+       unsigned int size = snd_pcm_lib_buffer_bytes(substream);
        int pos;
 
         if (!(chip->active & ADC1))
                 return 0;
-       pos = snd_dma_pointer(chip->dma1, chip->dma1_size);
+       pos = snd_dma_pointer(chip->dma1, size);
        return pos >> chip->dma1_shift;
 }
 
@@ -975,9 +965,6 @@ static int snd_es18xx_capture_close(struct snd_pcm_substream *substream)
 
 static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts4Source[4] = {
-               "Mic", "CD", "Line", "Master"
-       };
        static char *texts5Source[5] = {
                "Mic", "CD", "Line", "Master", "Mix"
        };
@@ -995,7 +982,8 @@ static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
                uinfo->value.enumerated.items = 4;
                if (uinfo->value.enumerated.item > 3)
                        uinfo->value.enumerated.item = 3;
-               strcpy(uinfo->value.enumerated.name, texts4Source[uinfo->value.enumerated.item]);
+               strcpy(uinfo->value.enumerated.name,
+                       texts5Source[uinfo->value.enumerated.item]);
                break;
        case 0x1887:
        case 0x1888:
@@ -1071,14 +1059,7 @@ static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
        return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal;
 }
 
-static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
+#define snd_es18xx_info_spatializer_enable     snd_ctl_boolean_mono_info
 
 static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -1120,14 +1101,7 @@ static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ct
        return 0;
 }
 
-static int snd_es18xx_info_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
+#define snd_es18xx_info_hw_switch      snd_ctl_boolean_stereo_info
 
 static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -1328,7 +1302,7 @@ ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
  * The chipset specific mixer controls
  */
 static struct snd_kcontrol_new snd_es18xx_opt_speaker =
-       ES18XX_SINGLE("PC Speaker Playback Volume", 0, 0x3c, 0, 7, 0);
+       ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0);
 
 static struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
 ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
@@ -1393,11 +1367,9 @@ ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
 static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
 {
        int data;
-       unsigned long flags;
-        spin_lock_irqsave(&chip->ctrl_lock, flags);
+
        outb(reg, chip->ctrl_port);
        data = inb(chip->ctrl_port + 1);
-        spin_unlock_irqrestore(&chip->ctrl_lock, flags);
        return data;
 }
 
@@ -1413,7 +1385,9 @@ static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
 #endif
 }
 
-static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
+static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
+                                          unsigned long mpu_port,
+                                          unsigned long fm_port)
 {
        int mask = 0;
 
@@ -1427,15 +1401,15 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
        if (chip->caps & ES18XX_CONTROL) {
                /* Hardware volume IRQ */
                snd_es18xx_config_write(chip, 0x27, chip->irq);
-               if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
+               if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
                        /* FM I/O */
-                       snd_es18xx_config_write(chip, 0x62, chip->fm_port >> 8);
-                       snd_es18xx_config_write(chip, 0x63, chip->fm_port & 0xff);
+                       snd_es18xx_config_write(chip, 0x62, fm_port >> 8);
+                       snd_es18xx_config_write(chip, 0x63, fm_port & 0xff);
                }
-               if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
+               if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) {
                        /* MPU-401 I/O */
-                       snd_es18xx_config_write(chip, 0x64, chip->mpu_port >> 8);
-                       snd_es18xx_config_write(chip, 0x65, chip->mpu_port & 0xff);
+                       snd_es18xx_config_write(chip, 0x64, mpu_port >> 8);
+                       snd_es18xx_config_write(chip, 0x65, mpu_port & 0xff);
                        /* MPU-401 IRQ */
                        snd_es18xx_config_write(chip, 0x28, chip->irq);
                }
@@ -1456,6 +1430,8 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
                snd_es18xx_write(chip, 0xB2, 0x50);
                /* Enable MPU and hardware volume interrupt */
                snd_es18xx_mixer_write(chip, 0x64, 0x42);
+               /* Enable ESS wavetable input */
+               snd_es18xx_mixer_bits(chip, 0x48, 0x10, 0x10);
        }
        else {
                int irqmask, dma1mask, dma2mask;
@@ -1520,11 +1496,12 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
                snd_es18xx_mixer_write(chip, 0x7A, 0x68);
                /* Enable and set hardware volume interrupt */
                snd_es18xx_mixer_write(chip, 0x64, 0x06);
-               if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
+               if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) {
                        /* MPU401 share irq with audio
                           Joystick enabled
                           FM enabled */
-                       snd_es18xx_mixer_write(chip, 0x40, 0x43 | (chip->mpu_port & 0xf0) >> 1);
+                       snd_es18xx_mixer_write(chip, 0x40,
+                                              0x43 | (mpu_port & 0xf0) >> 1);
                }
                snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01);
        }
@@ -1642,7 +1619,9 @@ static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
        return 0;
 }
 
-static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
+static int __devinit snd_es18xx_probe(struct snd_es18xx *chip,
+                                       unsigned long mpu_port,
+                                       unsigned long fm_port)
 {
        if (snd_es18xx_identify(chip) < 0) {
                snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
@@ -1663,8 +1642,6 @@ static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
                chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
                break;
        case 0x1887:
-               chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME;
-               break;
        case 0x1888:
                chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME;
                break;
@@ -1679,7 +1656,7 @@ static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
        if (chip->dma1 == chip->dma2)
                chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME);
 
-        return snd_es18xx_initialize(chip);
+       return snd_es18xx_initialize(chip, mpu_port, fm_port);
 }
 
 static struct snd_pcm_ops snd_es18xx_playback_ops = {
@@ -1704,8 +1681,10 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
        .pointer =      snd_es18xx_capture_pointer,
 };
 
-static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct snd_pcm ** rpcm)
+static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
+                                   struct snd_pcm **rpcm)
 {
+       struct snd_es18xx *chip = card->private_data;
         struct snd_pcm *pcm;
        char str[16];
        int err;
@@ -1714,9 +1693,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
                *rpcm = NULL;
        sprintf(str, "ES%x", chip->version);
        if (chip->caps & ES18XX_PCM2)
-               err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm);
+               err = snd_pcm_new(card, str, device, 2, 1, &pcm);
        else
-               err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm);
+               err = snd_pcm_new(card, str, device, 1, 1, &pcm);
         if (err < 0)
                 return err;
 
@@ -1747,10 +1726,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
 #ifdef CONFIG_PM
 static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
 {
-       struct snd_audiodrive *acard = card->private_data;
-       struct snd_es18xx *chip = acard->chip;
+       struct snd_es18xx *chip = card->private_data;
 
-       snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 
        snd_pcm_suspend_all(chip->pcm);
 
@@ -1765,24 +1743,25 @@ static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
 
 static int snd_es18xx_resume(struct snd_card *card)
 {
-       struct snd_audiodrive *acard = card->private_data;
-       struct snd_es18xx *chip = acard->chip;
+       struct snd_es18xx *chip = card->private_data;
 
        /* restore PM register, we won't wake till (not 0x07) i/o activity though */
        snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
 
-       snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
 #endif /* CONFIG_PM */
 
-static int snd_es18xx_free(struct snd_es18xx *chip)
+static int snd_es18xx_free(struct snd_card *card)
 {
+       struct snd_es18xx *chip = card->private_data;
+
        release_and_free_resource(chip->res_port);
        release_and_free_resource(chip->res_ctrl_port);
        release_and_free_resource(chip->res_mpu_port);
        if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) chip);
+               free_irq(chip->irq, (void *) card);
        if (chip->dma1 >= 0) {
                disable_dma(chip->dma1);
                free_dma(chip->dma1);
@@ -1791,93 +1770,82 @@ static int snd_es18xx_free(struct snd_es18xx *chip)
                disable_dma(chip->dma2);
                free_dma(chip->dma2);
        }
-       kfree(chip);
        return 0;
 }
 
 static int snd_es18xx_dev_free(struct snd_device *device)
 {
-       struct snd_es18xx *chip = device->device_data;
-       return snd_es18xx_free(chip);
+       return snd_es18xx_free(device->card);
 }
 
 static int __devinit snd_es18xx_new_device(struct snd_card *card,
                                           unsigned long port,
                                           unsigned long mpu_port,
                                           unsigned long fm_port,
-                                          int irq, int dma1, int dma2,
-                                          struct snd_es18xx ** rchip)
+                                          int irq, int dma1, int dma2)
 {
-        struct snd_es18xx *chip;
+       struct snd_es18xx *chip = card->private_data;
        static struct snd_device_ops ops = {
                .dev_free =     snd_es18xx_dev_free,
         };
        int err;
 
-       *rchip = NULL;
-        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->mixer_lock);
-       spin_lock_init(&chip->ctrl_lock);
-        chip->card = card;
         chip->port = port;
-        chip->mpu_port = mpu_port;
-        chip->fm_port = fm_port;
         chip->irq = -1;
         chip->dma1 = -1;
         chip->dma2 = -1;
         chip->audio2_vol = 0x00;
        chip->active = 0;
 
-       if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) {
-               snd_es18xx_free(chip);
+       chip->res_port = request_region(port, 16, "ES18xx");
+       if (chip->res_port == NULL) {
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
                return -EBUSY;
        }
 
-       if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx", (void *) chip)) {
-               snd_es18xx_free(chip);
+       if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx",
+                       (void *) card)) {
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
                return -EBUSY;
        }
        chip->irq = irq;
 
        if (request_dma(dma1, "ES18xx DMA 1")) {
-               snd_es18xx_free(chip);
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
                return -EBUSY;
        }
        chip->dma1 = dma1;
 
        if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
-               snd_es18xx_free(chip);
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
                return -EBUSY;
        }
        chip->dma2 = dma2;
 
-        if (snd_es18xx_probe(chip) < 0) {
-                snd_es18xx_free(chip);
-                return -ENODEV;
-        }
-       if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
-               snd_es18xx_free(chip);
+       if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) {
+               snd_es18xx_free(card);
+               return -ENODEV;
+       }
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+       if (err < 0) {
+               snd_es18xx_free(card);
                return err;
        }
-        *rchip = chip;
         return 0;
 }
 
-static int __devinit snd_es18xx_mixer(struct snd_es18xx *chip)
+static int __devinit snd_es18xx_mixer(struct snd_card *card)
 {
-       struct snd_card *card;
+       struct snd_es18xx *chip = card->private_data;
        int err;
        unsigned int idx;
 
-       card = chip->card;
-
        strcpy(card->mixername, chip->pcm->name);
 
        for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
@@ -1999,7 +1967,7 @@ 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_ISAPNP; /* Enable this card */
 #ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
 #endif
 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;    /* 0x220,0x240,0x260,0x280 */
 #ifndef CONFIG_PNP
@@ -2042,37 +2010,16 @@ static int pnpc_registered;
 
 static struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
        { .id = "ESS1869" },
+       { .id = "ESS1879" },
        { .id = "" }            /* end */
 };
 
 MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids);
 
 /* PnP main device initialization */
-static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev,
-                                                 struct pnp_resource_table *cfg)
+static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
 {
-       int err;
-
-       pnp_init_resource_table(cfg);
-       if (port[dev] != SNDRV_AUTO_PORT)
-               pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
-       if (fm_port[dev] != SNDRV_AUTO_PORT)
-               pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
-       if (mpu_port[dev] != SNDRV_AUTO_PORT)
-               pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2);
-       if (dma1[dev] != SNDRV_AUTO_DMA)
-               pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
-       if (dma2[dev] != SNDRV_AUTO_DMA)
-               pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
-       if (irq[dev] != SNDRV_AUTO_IRQ)
-               pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
-       if (pnp_device_is_isapnp(pdev)) {
-               err = pnp_manual_config_dev(pdev, cfg, 0);
-               if (err < 0)
-                       snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n");
-       }
-       err = pnp_activate_dev(pdev);
-       if (err < 0) {
+       if (pnp_activate_dev(pdev) < 0) {
                snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
                return -EBUSY;
        }
@@ -2097,19 +2044,12 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev,
        return 0;
 }
 
-static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
+static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
                                        struct pnp_dev *pdev)
 {
-       struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
-
-       if (!cfg)
-               return -ENOMEM;
-       acard->dev = pdev;
-       if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) {
-               kfree(cfg);
+       chip->dev = pdev;
+       if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
                return -EBUSY;
-       }
-       kfree(cfg);
        return 0;
 }
 
@@ -2134,37 +2074,28 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
 
 MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
 
-static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
+static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
                                        struct pnp_card_link *card,
                                        const struct pnp_card_device_id *id)
 {
-       struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
-
-       if (!cfg)
-               return -ENOMEM;
-       acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
-       if (acard->dev == NULL) {
-               kfree(cfg);
+       chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+       if (chip->dev == NULL)
                return -EBUSY;
-       }
-       acard->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
-       if (acard->devc == NULL) {
-               kfree(cfg);
+
+       chip->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
+       if (chip->devc == NULL)
                return -EBUSY;
-       }
+
        /* Control port initialization */
-       if (pnp_activate_dev(acard->devc) < 0) {
-               kfree(cfg);
+       if (pnp_activate_dev(chip->devc) < 0) {
                snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
                return -EAGAIN;
        }
        snd_printdd("pnp: port=0x%llx\n",
-                       (unsigned long long)pnp_port_start(acard->devc, 0));
-       if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) {
-               kfree(cfg);
+                       (unsigned long long)pnp_port_start(chip->devc, 0));
+       if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
                return -EBUSY;
-       }
-       kfree(cfg);
+
        return 0;
 }
 #endif /* CONFIG_PNP */
@@ -2175,27 +2106,23 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
 #define is_isapnp_selected(dev)                0
 #endif
 
-static struct snd_card *snd_es18xx_card_new(int dev)
+static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
 {
-       return snd_card_new(index[dev], id[dev], THIS_MODULE,
-                           sizeof(struct snd_audiodrive));
+       return snd_card_create(index[dev], id[dev], THIS_MODULE,
+                              sizeof(struct snd_es18xx), cardp);
 }
 
 static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
 {
-       struct snd_audiodrive *acard = card->private_data;
-       struct snd_es18xx *chip;
+       struct snd_es18xx *chip = card->private_data;
        struct snd_opl3 *opl3;
        int err;
 
-       if ((err = snd_es18xx_new_device(card,
-                                        port[dev],
-                                        mpu_port[dev],
-                                        fm_port[dev],
-                                        irq[dev], dma1[dev], dma2[dev],
-                                        &chip)) < 0)
+       err = snd_es18xx_new_device(card,
+                                   port[dev], mpu_port[dev], fm_port[dev],
+                                   irq[dev], dma1[dev], dma2[dev]);
+       if (err < 0)
                return err;
-       acard->chip = chip;
 
        sprintf(card->driver, "ES%x", chip->version);
        
@@ -2211,26 +2138,32 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
                        chip->port,
                        irq[dev], dma1[dev]);
 
-       if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
+       err = snd_es18xx_pcm(card, 0, NULL);
+       if (err < 0)
                return err;
 
-       if ((err = snd_es18xx_mixer(chip)) < 0)
+       err = snd_es18xx_mixer(card);
+       if (err < 0)
                return err;
 
        if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
-               if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
-                       snd_printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
+               if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
+                                   OPL3_HW_OPL3, 0, &opl3) < 0) {
+                       snd_printk(KERN_WARNING PFX
+                                  "opl3 not detected at 0x%lx\n",
+                                  fm_port[dev]);
                } else {
-                       if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+                       err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+                       if (err < 0)
                                return err;
                }
        }
 
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
-               if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
-                                              chip->mpu_port, 0,
-                                              irq[dev], 0,
-                                              &chip->rmidi)) < 0)
+               err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
+                                         mpu_port[dev], 0,
+                                         irq[dev], 0, &chip->rmidi);
+               if (err < 0)
                        return err;
        }
 
@@ -2247,9 +2180,9 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
        struct snd_card *card;
        int err;
 
-       card = snd_es18xx_card_new(dev);
-       if (! card)
-               return -ENOMEM;
+       err = snd_es18xx_card_new(dev, &card);
+       if (err < 0)
+               return err;
        snd_card_set_dev(card, devptr);
        if ((err = snd_audiodrive_probe(card, dev)) < 0) {
                snd_card_free(card);
@@ -2353,9 +2286,9 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
 
-       card = snd_es18xx_card_new(dev);
-       if (! card)
-               return -ENOMEM;
+       err = snd_es18xx_card_new(dev, &card);
+       if (err < 0)
+               return err;
        if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) {
                snd_card_free(card);
                return err;
@@ -2412,9 +2345,9 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
 
-       card = snd_es18xx_card_new(dev);
-       if (! card)
-               return -ENOMEM;
+       res = snd_es18xx_card_new(dev, &card);
+       if (res < 0)
+               return res;
 
        if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) {
                snd_card_free(card);