You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


ChangeSet@1.644, 2002-10-01 08:18:44+02:00, perex@suse.cz
  ALSA update 2002/08/09 :
    - Corrections for PCM sample silence (24-bits)
    - OPL3 code fixes (delays)
    - CS4281
      - added the power management code
      - added mixer controls for internal FM and PCM volumes
    - EMU10K1
      - fixed the dma mask
    - ICE1712
      - replaced EREMOTE with EIO
      - check the return value from ews88mt_chip_select()
    - Maestro3
      - corrected the wrong pci id for inspiron 8000
      - use the quirk list for gpio workarounds


 include/sound/version.h          |    2 
 sound/arm/sa11xx-uda1341.c       |    2 
 sound/core/ioctl32/ioctl32.c     |    1 
 sound/core/pcm_misc.c            |   30 ++-
 sound/core/pcm_native.c          |    1 
 sound/drivers/opl3/opl3_lib.c    |    2 
 sound/pci/Config.in              |    2 
 sound/pci/cs4281.c               |  385 ++++++++++++++++++++++++++++++++++-----
 sound/pci/emu10k1/emu10k1_main.c |   30 +--
 sound/pci/ice1712.c              |   53 +++--
 sound/pci/maestro3.c             |   84 ++++++--
 11 files changed, 477 insertions(+), 115 deletions(-)


diff -Nru a/include/sound/version.h b/include/sound/version.h
--- a/include/sound/version.h	Tue Oct  1 17:05:36 2002
+++ b/include/sound/version.h	Tue Oct  1 17:05:36 2002
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated automatically by configure.  */
 #define CONFIG_SND_VERSION "0.9.0rc2"
-#define CONFIG_SND_DATE " (Mon Aug 05 14:24:05 2002 UTC)"
+#define CONFIG_SND_DATE " (Fri Aug 09 11:49:03 2002 UTC)"
diff -Nru a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
--- a/sound/arm/sa11xx-uda1341.c	Tue Oct  1 17:05:36 2002
+++ b/sound/arm/sa11xx-uda1341.c	Tue Oct  1 17:05:36 2002
@@ -15,7 +15,7 @@
  * 2002-04-04   Tomas Kasparek  better rates handling (allow non-standard rates)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.3 2002/05/25 10:26:06 perex Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.4 2002/08/06 18:03:25 perex Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
diff -Nru a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
--- a/sound/core/ioctl32/ioctl32.c	Tue Oct  1 17:05:36 2002
+++ b/sound/core/ioctl32/ioctl32.c	Tue Oct  1 17:05:36 2002
@@ -460,7 +460,6 @@
 		return err;
 	}
 #endif
-
 	return 0;
 }
 
diff -Nru a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
--- a/sound/core/pcm_misc.c	Tue Oct  1 17:05:36 2002
+++ b/sound/core/pcm_misc.c	Tue Oct  1 17:05:36 2002
@@ -329,6 +329,18 @@
 		return 0x0000800000008000ULL;
 	case SNDRV_PCM_FORMAT_U32_BE:
 		return 0x0000008000000080ULL;
+	case SNDRV_PCM_FORMAT_U24_3LE:
+		return 0x0000800000800000ULL;
+	case SNDRV_PCM_FORMAT_U24_3BE:
+		return 0x0080000080000080ULL;
+	case SNDRV_PCM_FORMAT_U20_3LE:
+		return 0x0000080000080000ULL;
+	case SNDRV_PCM_FORMAT_U20_3BE:
+		return 0x0008000008000008ULL;
+	case SNDRV_PCM_FORMAT_U18_3LE:
+		return 0x0000020000020000ULL;
+	case SNDRV_PCM_FORMAT_U18_3BE:
+		return 0x0002000002000002ULL;
 #else
 	case SNDRV_PCM_FORMAT_U16_LE:
 		return 0x0080008000800080ULL;
@@ -342,16 +354,19 @@
 		return 0x0080000000800000ULL;
 	case SNDRV_PCM_FORMAT_U32_BE:
 		return 0x8000000080000000ULL;
-#endif
 	case SNDRV_PCM_FORMAT_U24_3LE:
+		return 0x0080000080000080ULL;
 	case SNDRV_PCM_FORMAT_U24_3BE:
 		return 0x0000800000800000ULL;
 	case SNDRV_PCM_FORMAT_U20_3LE:
+		return 0x0008000008000008ULL;
 	case SNDRV_PCM_FORMAT_U20_3BE:
 		return 0x0000080000080000ULL;
 	case SNDRV_PCM_FORMAT_U18_3LE:
+		return 0x0002000002000002ULL;
 	case SNDRV_PCM_FORMAT_U18_3BE:
 		return 0x0000020000020000ULL;
+#endif
 	case SNDRV_PCM_FORMAT_FLOAT_LE:
 	{
 		union {
@@ -471,11 +486,16 @@
 		if (! silence)
 			memset(data, 0, samples * 3);
 		else {
-			/* FIXME: rewrite in the more better way.. */
-			int i;
 			while (samples-- > 0) {
-				for (i = 0; i < 3; i++)
-					*((u_int8_t *)data)++ = silence >> (i * 8);
+#ifdef SNDRV_LITTLE_ENDIAN
+				*((u_int8_t *)data)++ = silence >> 0;
+				*((u_int8_t *)data)++ = silence >> 8;
+				*((u_int8_t *)data)++ = silence >> 16;
+#else
+				*((u_int8_t *)data)++ = silence >> 16;
+				*((u_int8_t *)data)++ = silence >> 8;
+				*((u_int8_t *)data)++ = silence >> 0;
+#endif
 			}
 		}
 	}
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	Tue Oct  1 17:05:36 2002
+++ b/sound/core/pcm_native.c	Tue Oct  1 17:05:36 2002
@@ -1616,7 +1616,6 @@
 	snd_assert(err >= 0, return -EINVAL);
 
 	err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
-	//err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
 	snd_assert(err >= 0, return -EINVAL);
 
 	err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
diff -Nru a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
--- a/sound/drivers/opl3/opl3_lib.c	Tue Oct  1 17:05:36 2002
+++ b/sound/drivers/opl3/opl3_lib.c	Tue Oct  1 17:05:36 2002
@@ -101,8 +101,10 @@
 	spin_lock_irqsave(&opl3->reg_lock, flags);
 
 	writel((unsigned int)cmd, port << 2);
+	udelay(10);
 
 	writel((unsigned int)val, (port + 1) << 2);
+	udelay(30);
 
 	spin_unlock_irqrestore(&opl3->reg_lock, flags);
 }
diff -Nru a/sound/pci/Config.in b/sound/pci/Config.in
--- a/sound/pci/Config.in	Tue Oct  1 17:05:36 2002
+++ b/sound/pci/Config.in	Tue Oct  1 17:05:36 2002
@@ -6,7 +6,7 @@
 dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND
 dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND
 dep_mbool '  Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)' CONFIG_SND_CS46XX_NEW_DSP $CONFIG_SND_CS46XX $CONFIG_EXPERIMENTAL
-dep_tristate 'Cirrus Logic CS4281' CONFIG_SND_CS4281 $CONFIG_SND
+dep_tristate 'Cirrus Logic (Sound Fusion) CS4281' CONFIG_SND_CS4281 $CONFIG_SND
 dep_tristate 'EMU10K1 (SB Live!, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND
 dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND
 dep_tristate 'NeoMagic NM256AV/ZX' CONFIG_SND_NM256 $CONFIG_SND
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c	Tue Oct  1 17:05:36 2002
+++ b/sound/pci/cs4281.c	Tue Oct  1 17:05:36 2002
@@ -362,6 +362,8 @@
 #define BA0_SRCSA		0x075c	/* SRC Slot Assignments */
 #define BA0_PPLVC		0x0760	/* PCM Playback Left Volume Control */
 #define BA0_PPRVC		0x0764	/* PCM Playback Right Volume Control */
+#define BA0_PASR		0x0768	/* playback sample rate */
+#define BA0_CASR		0x076C	/* capture sample rate */
 
 /* Source Slot Numbers - Playback */
 #define SRCSLOT_LEFT_PCM_PLAYBACK		0
@@ -465,6 +467,8 @@
 	int frag;			/* period number */
 };
 
+#define SUSPEND_REGISTERS	20
+
 struct snd_cs4281 {
 	int irq;
 
@@ -506,6 +510,11 @@
 	snd_info_entry_t *proc_entry;
 
 	struct snd_cs4281_gameport *gameport;
+
+#ifdef CONFIG_PM
+	u32 suspend_regs[SUSPEND_REGISTERS];
+#endif
+
 };
 
 static void snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -527,23 +536,35 @@
  *  common I/O routines
  */
 
-static void snd_cs4281_delay(unsigned int delay)
+static void snd_cs4281_delay(unsigned int delay, int can_schedule)
 {
 	if (delay > 999) {
-		signed long end_time;
-		delay = (delay * HZ) / 1000000;
-		if (delay < 1)
-			delay = 1;
-		end_time = jiffies + delay;
-		do {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(1);
-	        } while (end_time - (signed long)jiffies >= 0);
+		if (can_schedule) {
+			signed long end_time;
+			delay = (delay * HZ) / 1000000;
+			if (delay < 1)
+				delay = 1;
+			end_time = jiffies + delay;
+			do {
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(1);
+			} while (end_time - (signed long)jiffies >= 0);
+		} else
+			mdelay(delay);
 	} else {
 		udelay(delay);
 	}
 }
 
+inline static void snd_cs4281_delay_long(int can_schedule)
+{
+	if (can_schedule) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	} else
+		mdelay(1999 / HZ);
+}
+
 static inline void snd_cs4281_pokeBA0(cs4281_t *chip, unsigned long offset, unsigned int val)
 {
         writel(val, chip->ba0 + offset);
@@ -717,6 +738,9 @@
 		dma->valDMR &= ~(BA0_DMR_DMA|BA0_DMR_POLL);
 		dma->valDCR |= BA0_DCR_MSK;
 		dma->valFCR &= ~BA0_FCR_FEN;
+		/* Leave wave playback FIFO enabled for FM */
+		if (dma->regFCR != BA0_FCR0)
+			dma->valFCR &= ~BA0_FCR_FEN;
 		break;
 	default:
 		spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -800,12 +824,18 @@
 		}
 	}
       __skip_src:
+	/* Deactivate wave playback FIFO before changing slot assignments */
+	if (dma->regFCR == BA0_FCR0)
+		snd_cs4281_pokeBA0(chip, dma->regFCR, snd_cs4281_peekBA0(chip, dma->regFCR) & ~BA0_FCR_FEN);
 	/* Initialize FIFO */
 	dma->valFCR = BA0_FCR_LS(dma->left_slot) |
 		      BA0_FCR_RS(capture && (dma->valDMR & BA0_DMR_MONO) ? 31 : dma->right_slot) |
 		      BA0_FCR_SZ(CS4281_FIFO_SIZE) |
 		      BA0_FCR_OF(dma->fifo_offset);
 	snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | (capture ? BA0_FCR_PSH : 0));
+	/* Activate FIFO again for FM playback */
+	if (dma->regFCR == BA0_FCR0)
+		snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | BA0_FCR_FEN);
 	/* Clear FIFO Status and Interrupt Control Register */
 	snd_cs4281_pokeBA0(chip, dma->regFSIC, 0);
 }
@@ -855,7 +885,7 @@
 
 	// printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies);
 	return runtime->buffer_size -
-	       snd_cs4281_peekBA0(chip, dma->regDCC);
+	       snd_cs4281_peekBA0(chip, dma->regDCC) - 1;
 }
 
 static snd_pcm_hardware_t snd_cs4281_playback =
@@ -1024,6 +1054,76 @@
  *  Mixer section
  */
 
+#define CS_VOL_MASK	0x1f
+
+static int snd_cs4281_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type              = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count             = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = CS_VOL_MASK;
+	return 0;
+}
+ 
+static int snd_cs4281_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	cs4281_t *chip = snd_kcontrol_chip(kcontrol);
+	int regL = (kcontrol->private_value >> 16) & 0xffff;
+	int regR = kcontrol->private_value & 0xffff;
+	int volL, volR;
+
+	volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK);
+	volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK);
+
+	ucontrol->value.integer.value[0] = volL;
+	ucontrol->value.integer.value[1] = volR;
+	return 0;
+}
+
+static int snd_cs4281_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	cs4281_t *chip = snd_kcontrol_chip(kcontrol);
+	int change = 0;
+	int regL = (kcontrol->private_value >> 16) & 0xffff;
+	int regR = kcontrol->private_value & 0xffff;
+	int volL, volR;
+
+	volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK);
+	volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK);
+
+	if (ucontrol->value.integer.value[0] != volL) {
+		volL = CS_VOL_MASK - (ucontrol->value.integer.value[0] & CS_VOL_MASK);
+		snd_cs4281_pokeBA0(chip, regL, volL);
+		change = 1;
+	}
+	if (ucontrol->value.integer.value[0] != volL) {
+		volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK);
+		snd_cs4281_pokeBA0(chip, regR, volR);
+		change = 1;
+	}
+	return change;
+}
+
+static snd_kcontrol_new_t snd_cs4281_fm_vol = 
+{
+	iface: SNDRV_CTL_ELEM_IFACE_MIXER,
+	name: "Synth Playback Volume",
+	info: snd_cs4281_info_volume, 
+	get: snd_cs4281_get_volume,
+	put: snd_cs4281_put_volume, 
+	private_value: ((BA0_FMLVC << 16) | BA0_FMRVC),
+};
+
+static snd_kcontrol_new_t snd_cs4281_pcm_vol = 
+{
+	iface: SNDRV_CTL_ELEM_IFACE_MIXER,
+	name: "PCM Stream Playback Volume",
+	info: snd_cs4281_info_volume, 
+	get: snd_cs4281_get_volume,
+	put: snd_cs4281_put_volume, 
+	private_value: ((BA0_PPLVC << 16) | BA0_PPRVC),
+};
+
 static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
 {
 	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
@@ -1051,11 +1151,16 @@
 		if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97_secondary)) < 0)
 			return err;
 	}
+	if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip))) < 0)
+		return err;
+	if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip))) < 0)
+		return err;
 	return 0;
 }
 
-/*
 
+/*
+ * proc interface
  */
 
 static void snd_cs4281_proc_read(snd_info_entry_t *entry, 
@@ -1337,14 +1442,18 @@
 	return snd_cs4281_free(chip);
 }
 
+static int snd_cs4281_chip_init(cs4281_t *chip, int can_schedule); /* defined below */
+#ifdef CONFIG_PM
+static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state);
+#endif
+
 static int __devinit snd_cs4281_create(snd_card_t * card,
-				    struct pci_dev *pci,
-				    cs4281_t ** rchip,
+				       struct pci_dev *pci,
+				       cs4281_t ** rchip,
 				       int dual_codec)
 {
 	cs4281_t *chip;
 	unsigned int tmp;
-	signed long end_time;
 	int err;
 	static snd_device_ops_t ops = {
 		dev_free:	snd_cs4281_dev_free,
@@ -1393,13 +1502,39 @@
 		return -ENOMEM;
 	}
 	
+	tmp = snd_cs4281_chip_init(chip, 0);
+	if (tmp) {
+		snd_cs4281_free(chip);
+		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;
+	}
+
+	*rchip = chip;
+	return 0;
+}
+
+static int snd_cs4281_chip_init(cs4281_t *chip, int can_schedule)
+{
+	unsigned int tmp;
+	int timeout;
+
 	tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
 	if (tmp != BA0_CFLR_DEFAULT) {
 		snd_cs4281_pokeBA0(chip, BA0_CFLR, BA0_CFLR_DEFAULT);
 		tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
 		if (tmp != BA0_CFLR_DEFAULT) {
 			snd_printk(KERN_ERR "CFLR setup failed (0x%x)\n", tmp);
-			snd_cs4281_free(chip);
 			return -EIO;
 		}
 	}
@@ -1411,12 +1546,10 @@
 	
 	if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) {
 		snd_printk(KERN_ERR "SERC1 AC'97 check failed (0x%x)\n", tmp);
-		snd_cs4281_free(chip);
 		return -EIO;
 	}
 	if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) {
 		snd_printk(KERN_ERR "SERC2 AC'97 check failed (0x%x)\n", tmp);
-		snd_cs4281_free(chip);
 		return -EIO;
 	}
 
@@ -1445,7 +1578,7 @@
 	snd_cs4281_pokeBA0(chip, BA0_SPMC, 0);
 	udelay(50);
 	snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN);
-	snd_cs4281_delay(50000);
+	snd_cs4281_delay(50000, can_schedule);
 
 	if (chip->dual_codec)
 		snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E);
@@ -1461,13 +1594,13 @@
 	 *  Start the DLL Clock logic.
 	 */
 	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_DLLP);
-	snd_cs4281_delay(50000);
+	snd_cs4281_delay(50000, can_schedule);
 	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_SWCE | BA0_CLKCR1_DLLP);
 
 	/*
 	 * Wait for the DLL ready signal from the clock logic.
 	 */
-	end_time = (jiffies + HZ / 4) + 1;
+	timeout = HZ;
 	do {
 		/*
 		 *  Read the AC97 status register to see if we've seen a CODEC
@@ -1475,12 +1608,10 @@
 		 */
 		if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
 			goto __ok0;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-        } while (end_time - (signed long)jiffies >= 0);
+		snd_cs4281_delay_long(can_schedule);
+	} while (timeout-- > 0);
 
 	snd_printk(KERN_ERR "DLLRDY not seen\n");
-	snd_cs4281_free(chip);
 	return -EIO;
 
       __ok0:
@@ -1495,7 +1626,7 @@
 	/*
 	 * Wait for the codec ready signal from the AC97 codec.
 	 */
-	end_time = (jiffies + (3 * HZ) / 4) + 1;
+	timeout = HZ;
 	do {
 		/*
 		 *  Read the AC97 status register to see if we've seen a CODEC
@@ -1503,23 +1634,20 @@
 		 */
 		if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
 			goto __ok1;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-        } while (end_time - (signed long)jiffies >= 0);
+		snd_cs4281_delay_long(can_schedule);
+	} while (timeout-- > 0);
 
 	snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
-	snd_cs4281_free(chip);
 	return -EIO;
 
       __ok1:
 	if (chip->dual_codec) {
-		end_time = (jiffies + (3 * HZ) / 4) + 1;
+		timeout = HZ;
 		do {
 			if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
 				goto __codec2_ok;
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(1);
-		} while (end_time - (signed long)jiffies >= 0);
+			snd_cs4281_delay_long(can_schedule);
+		} while (timeout-- > 0);
 		snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
 		chip->dual_codec = 0;
 	__codec2_ok: ;
@@ -1537,7 +1665,7 @@
 	 *  the codec is pumping ADC data across the AC-link.
 	 */
 
-	end_time = (jiffies + (5 * HZ) / 4) + 1;
+	timeout = HZ;
 	do {
 		/*
 		 *  Read the input slot valid register and see if input slots 3
@@ -1545,12 +1673,10 @@
 		 */
                 if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
                         goto __ok2;
-                set_current_state(TASK_UNINTERRUPTIBLE);
-                schedule_timeout(1);
-        } while (end_time - (signed long)jiffies >= 0);
+		snd_cs4281_delay_long(can_schedule);
+	} while (timeout-- > 0);
 
 	snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n");
-	snd_cs4281_free(chip);
 	return -EIO;
 
       __ok2:
@@ -1588,12 +1714,21 @@
 	chip->src_left_rec_slot = 10;	/* AC'97 left PCM record (3) */
 	chip->src_right_rec_slot = 11;	/* AC'97 right PCM record (4) */
 
+	/* Activate wave playback FIFO for FM playback */
+	chip->dma[0].valFCR = BA0_FCR_FEN | BA0_FCR_LS(0) |
+		              BA0_FCR_RS(1) |
+ 	  	              BA0_FCR_SZ(CS4281_FIFO_SIZE) |
+		              BA0_FCR_OF(chip->dma[0].fifo_offset);
+	snd_cs4281_pokeBA0(chip, chip->dma[0].regFCR, chip->dma[0].valFCR);
+	snd_cs4281_pokeBA0(chip, BA0_SRCSA, (chip->src_left_play_slot << 0) |
+					    (chip->src_right_play_slot << 8) |
+					    (chip->src_left_rec_slot << 16) |
+					    (chip->src_right_rec_slot << 24));
+
 	/* Initialize digital volume */
 	snd_cs4281_pokeBA0(chip, BA0_PPLVC, 0);
 	snd_cs4281_pokeBA0(chip, BA0_PPRVC, 0);
 
-	snd_cs4281_proc_init(chip);
-
 	/* Enable IRQs */
 	snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_EOI);
 	/* Unmask interrupts */
@@ -1606,12 +1741,6 @@
 					BA0_HISR_DMA(3)));
 	synchronize_irq(chip->irq);
 
-	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
-		snd_cs4281_free(chip);
-		return err;
-	}
-
-	*rchip = chip;
 	return 0;
 }
 
@@ -1917,22 +2046,180 @@
 		return err;
 	}
 
-	pci_set_drvdata(pci, card);
+	pci_set_drvdata(pci, chip);
 	dev++;
 	return 0;
 }
 
 static void __devexit snd_cs4281_remove(struct pci_dev *pci)
 {
-	snd_card_free(pci_get_drvdata(pci));
+	cs4281_t *chip = pci_get_drvdata(pci);
+	snd_card_free(chip->card);
 	pci_set_drvdata(pci, NULL);
 }
 
+/*
+ * Power Management
+ */
+#ifdef CONFIG_PM
+
+static int saved_regs[SUSPEND_REGISTERS] = {
+	BA0_JSCTL,
+	BA0_GPIOR,
+	BA0_SSCR,
+	BA0_MIDCR,
+	BA0_SRCSA,
+	BA0_PASR,
+	BA0_CASR,
+	BA0_DACSR,
+	BA0_ADCSR,
+	BA0_FMLVC,
+	BA0_FMRVC,
+	BA0_PPLVC,
+	BA0_PPRVC,
+};
+
+#define number_of(array)	(sizeof(array) / sizeof(array[0]))
+
+#define CLKCR1_CKRA                             0x00010000L
+
+static void cs4281_suspend(cs4281_t *chip)
+{
+	snd_card_t *card = chip->card;
+	u32 ulCLK;
+	int i;
+
+	snd_power_lock(card);
+	if (card->power_state == SNDRV_CTL_POWER_D3hot)
+		goto __skip;
+
+	snd_pcm_suspend_all(chip->pcm);
+
+	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
+	ulCLK |= CLKCR1_CKRA;
+	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
+
+	/* Disable interrupts. */
+	snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
+
+	/* remember the status registers */
+	for (i = 0; number_of(saved_regs); i++)
+		chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
+
+	/* Turn off the serial ports. */
+	snd_cs4281_pokeBA0(chip, BA0_SERMC, 0);
+
+	/* Power off FM, Joystick, AC link, */
+	snd_cs4281_pokeBA0(chip, BA0_SSPM, 0);
+
+	/* DLL off. */
+	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0);
+
+	/* AC link off. */
+	snd_cs4281_pokeBA0(chip, BA0_SPMC, 0);
+
+	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
+	ulCLK &= ~CLKCR1_CKRA;
+	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ __skip:
+      	snd_power_unlock(card);
+}
+
+static void cs4281_resume(cs4281_t *chip)
+{
+	snd_card_t *card = chip->card;
+	int i;
+	u32 ulCLK;
+
+	snd_power_lock(card);
+	if (card->power_state == SNDRV_CTL_POWER_D0)
+		goto __skip;
+
+	pci_enable_device(chip->pci);
+
+	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
+	ulCLK |= CLKCR1_CKRA;
+	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
+
+	snd_cs4281_chip_init(chip, 0);
+
+	/* restore the status registers */
+	for (i = 0; number_of(saved_regs); i++)
+		snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);
+
+	if (chip->ac97)
+		snd_ac97_resume(chip->ac97);
+	if (chip->ac97_secondary)
+		snd_ac97_resume(chip->ac97_secondary);
+
+	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
+	ulCLK &= ~CLKCR1_CKRA;
+	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+      __skip:
+      	snd_power_unlock(card);
+}
+
+#ifndef PCI_OLD_SUSPEND
+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;
+}
+#else
+static void snd_cs4281_suspend(struct pci_dev *dev)
+{
+	cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return);
+	cs4281_suspend(chip);
+}
+static void snd_cs4281_resume(struct pci_dev *dev)
+{
+	cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return);
+	cs4281_resume(chip);
+}
+#endif
+
+/* 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 = {
 	name: "CS4281",
 	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
 };
 	
 static int __init alsa_card_cs4281_init(void)
diff -Nru a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
--- a/sound/pci/emu10k1/emu10k1_main.c	Tue Oct  1 17:05:36 2002
+++ b/sound/pci/emu10k1/emu10k1_main.c	Tue Oct  1 17:05:36 2002
@@ -534,24 +534,31 @@
 {
 	emu10k1_t *emu;
 	int err;
+	int is_audigy;
 	static snd_device_ops_t ops = {
 		dev_free:	snd_emu10k1_dev_free,
 	};
 	
 	*remu = NULL;
 
+	// is_audigy = (int)pci->driver_data;
+	is_audigy = (pci->device == 0x0004);
+
 	/* enable PCI device */
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	/* check, if we can restrict PCI DMA transfers to 31 bits */
-	if (!pci_dma_supported(pci, 0x7fffffff)) {
-		snd_printk("architecture does not support 31bit PCI busmaster DMA\n");
-		return -ENXIO;
+	/* set the DMA transfer mask */
+	if (is_audigy) {
+		if (pci_set_dma_mask(pci, 0xffffffff) < 0) {
+			snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
+			return -ENXIO;
+		}
+	} else {
+		if (pci_set_dma_mask(pci, 0x1fffffff) < 0) {
+			snd_printk(KERN_ERR "architecture does not support 29bit PCI busmaster DMA\n");
+			return -ENXIO;
+		}
 	}
-	if (pci_get_drvdata(pci))
-		pci_set_dma_mask(pci, 0xffffffff); /* audigy */
-	else
-		pci_set_dma_mask(pci, 0x7fffffff);
 
 	emu = snd_magic_kcalloc(emu10k1_t, 0, GFP_KERNEL);
 	if (emu == NULL)
@@ -572,11 +579,8 @@
 	emu->get_synth_voice = NULL;
 	emu->port = pci_resource_start(pci, 0);
 
-	// emu->audigy = (int)pci->driver_data;
-	if (pci->device == 0x0004)
-		emu->audigy = 1;
-
-	if (emu->audigy)
+	emu->audigy = is_audigy;
+	if (is_audigy)
 		emu->gpr_base = A_FXGPREGBASE;
 	else
 		emu->gpr_base = FXGPREGBASE;
diff -Nru a/sound/pci/ice1712.c b/sound/pci/ice1712.c
--- a/sound/pci/ice1712.c	Tue Oct  1 17:05:36 2002
+++ b/sound/pci/ice1712.c	Tue Oct  1 17:05:36 2002
@@ -960,17 +960,25 @@
 };
 
 /* AK4524 chip select; address 0x48 bit 0-3 */
-static void snd_ice1712_ews88mt_chip_select(ice1712_t *ice, int chip_mask)
+static int snd_ice1712_ews88mt_chip_select(ice1712_t *ice, int chip_mask)
 {
 	unsigned char data, ndata;
 
-	snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return);
+	snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return -EINVAL);
 	snd_i2c_lock(ice->i2c);
-	snd_runtime_check(snd_i2c_readbytes(ice->pcf8574[1], &data, 1) == 1, snd_i2c_unlock(ice->i2c); return);
+	if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1)
+		goto __error;
 	ndata = (data & 0xf0) | chip_mask;
 	if (ndata != data)
-		snd_runtime_check(snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) == 1, snd_i2c_unlock(ice->i2c); return);
+		if (snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) != 1)
+			goto __error;
 	snd_i2c_unlock(ice->i2c);
+	return 0;
+
+     __error:
+	snd_i2c_unlock(ice->i2c);
+	snd_printk(KERN_ERR "AK4524 chip select failed, check cable to the front module\n");
+	return -EIO;
 }
 
 /*
@@ -988,7 +996,8 @@
 
 	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_EWS88MT) {
 		/* assert AK4524 CS */
-		snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f);
+		if (snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f) < 0)
+			return;
 		//snd_ice1712_ews88mt_chip_select(ice, 0x0f);
 	}
 
@@ -1147,11 +1156,11 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_sendbytes(ice->cs8427, reg, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	if (snd_i2c_readbytes(ice->cs8427, &val, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	nval = val & 0xf0;
 	if (spdif_clock)
@@ -1161,7 +1170,7 @@
 	if (val != nval) {
 		reg[1] = nval;
 		if (snd_i2c_sendbytes(ice->cs8427, reg, 2) != 2) {
-			res = -EREMOTE;
+			res = -EIO;
 		} else {
 			res++;
 		}
@@ -3187,7 +3196,7 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	ucontrol->value.enumerated.item[0] = data & ICE1712_EWS88MT_OUTPUT_SENSE ? 1 : 0; /* high = -10dBV, low = +4dBu */
@@ -3203,12 +3212,12 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0);
 	if (ndata != data && snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	return ndata != data;
@@ -3225,7 +3234,7 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_readbytes(ice->pcf8574[0], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	/* reversed; high = +4dBu, low = -10dBV */
 	ucontrol->value.enumerated.item[0] = data & (1 << channel) ? 0 : 1;
@@ -3243,12 +3252,12 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_readbytes(ice->pcf8574[0], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel));
 	if (ndata != data && snd_i2c_sendbytes(ice->pcf8574[0], &ndata, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	return ndata != data;
@@ -3294,7 +3303,7 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_readbytes(ice->pcf8575, data, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	data[0] = (data[shift >> 3] >> (shift & 7)) & 0x01;
@@ -3315,7 +3324,7 @@
 	snd_i2c_lock(ice->i2c);
 	if (snd_i2c_readbytes(ice->pcf8575, data, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	ndata[shift >> 3] = data[shift >> 3] & ~(1 << (shift & 7));
 	if (invert) {
@@ -3328,7 +3337,7 @@
 	change = (data[shift >> 3] != ndata[shift >> 3]);
 	if (change && snd_i2c_sendbytes(ice->pcf8575, data, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	return change;
@@ -3366,7 +3375,7 @@
 	snd_i2c_sendbytes(ice->pcf8575, &byte, 1);
 	if (snd_i2c_readbytes(ice->pcf8575, &byte, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	return byte;
@@ -3380,7 +3389,7 @@
 	bytes[1] = data;
 	if (snd_i2c_sendbytes(ice->pcf8575, bytes, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
-		return -EREMOTE;
+		return -EIO;
 	}
 	snd_i2c_unlock(ice->i2c);
 	return 0;
@@ -3836,11 +3845,15 @@
 	}
 	/* second stage of initialization, analog parts and others */
 	switch (ice->eeprom.subvendor) {
+	case ICE1712_SUBDEVICE_EWS88MT:
+		/* Check if the front module is connected */
+		if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0)
+			return err;
+		/* Fall through */
 	case ICE1712_SUBDEVICE_DELTA66:
 	case ICE1712_SUBDEVICE_DELTA44:
 	case ICE1712_SUBDEVICE_AUDIOPHILE:
 	case ICE1712_SUBDEVICE_EWX2496:
-	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_DMX6FIRE:
 		snd_ice1712_ak4524_init(ice);
 		break;
diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c
--- a/sound/pci/maestro3.c	Tue Oct  1 17:05:36 2002
+++ b/sound/pci/maestro3.c	Tue Oct  1 17:05:36 2002
@@ -776,6 +776,14 @@
 #define chip_t m3_t
 
 
+/* quirk lists */
+struct m3_quirk {
+	u16 vendor, device;	/* subsystem ids */
+	int amp_gpio;		/* gpio pin #  for external amp, -1 = default */
+	int irda_workaround;	/* non-zero if avoid to touch 0x10 on GPIO_DIRECTION
+				   (e.g. for IrDA on Dell Inspirons) */
+};
+
 struct m3_list {
 	int curlen;
 	int mem_addr;
@@ -825,9 +833,7 @@
 	snd_pcm_t *pcm;
 
 	struct pci_dev *pci;
-	/* pci_dev in 2.2 kernel doesn't have them, so we keep them private */
-	u16 subsystem_vendor;
-	u16 subsystem_device;
+	struct m3_quirk *quirk;
 
 	int dacs_active;
 	int timer_users;
@@ -908,6 +914,33 @@
 
 MODULE_DEVICE_TABLE(pci, snd_m3_ids);
 
+static struct m3_quirk m3_quirk_list[] = {
+	/* panasonic CF-28 "toughbook" */
+	{
+		vendor: 0x10f7,
+		device: 0x833e,
+		amp_gpio: 0x0d,
+	},
+	/* Dell Inspiron 4000 */
+	{
+		vendor: 0x1028,
+		device: 0x00b0,
+		amp_gpio: -1,
+		irda_workaround: 1,
+	},
+	/* Dell Inspiron 8000 */
+	{
+		vendor: 0x1028,
+		device: 0x00a4,
+		amp_gpio: -1,
+		irda_workaround: 1,
+	},
+	/* FIXME: Inspiron 8100 and 8200 ids should be here, too */
+	/* END */
+	{ 0 }
+};
+
+
 /*
  * lowlevel functions
  */
@@ -1859,10 +1892,7 @@
 
 	for (i = 0; i < 5; i++) {
 		dir = inw(io + GPIO_DIRECTION);
-		if (chip->subsystem_vendor == 0x1028 &&
-		    chip->subsystem_device == 0x00b0) /* Dell Inspiron 4000 */
-			; /* seems conflicting with IrDA */
-		else
+		if (! chip->quirk || ! chip->quirk->irda_workaround)
 			dir |= 0x10; /* assuming pci bus master? */
 
 		snd_m3_remote_codec_config(io, 0);
@@ -2470,6 +2500,8 @@
 {
 	m3_t *chip;
 	int i, err;
+	struct m3_quirk *quirk;
+	u16 subsystem_vendor, subsystem_device;
 	static snd_device_ops_t ops = {
 		dev_free:	snd_m3_dev_free,
 	};
@@ -2500,29 +2532,35 @@
 		break;
 	}
 
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+
 #ifndef LINUX_2_2
-	chip->subsystem_vendor = pci->subsystem_vendor;
-	chip->subsystem_device = pci->subsystem_device;
+	subsystem_vendor = pci->subsystem_vendor;
+	subsystem_device = pci->subsystem_device;
 #else
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->subsystem_vendor);
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->subsystem_device);
+	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
 #endif
+	for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
+		if (subsystem_vendor == quirk->vendor &&
+		    subsystem_device == quirk->device) {
+			chip->quirk = quirk;
+			break;
+		}
+	}
 
-	chip->card = card;
-	chip->pci = pci;
-	chip->irq = -1;
 	chip->external_amp = enable_amp;
 	if (amp_gpio >= 0 && amp_gpio <= 0x0f)
 		chip->amp_gpio = amp_gpio;
-	else if (chip->allegro_flag) {
-		/* panasonic CF-28 "toughbook" has different GPIO connection.. */
-		if (chip->subsystem_vendor == 0x10f7 &&
-		    chip->subsystem_device == 0x833e)
-			chip->amp_gpio = 0x0d;
-		else
-			chip->amp_gpio = GPO_EXT_AMP_ALLEGRO;
-	} else
-		chip->amp_gpio = GPO_EXT_AMP_M3; /* presumably this is for all 'maestro3's.. */
+	else if (chip->quirk && chip->quirk->amp_gpio >= 0)
+		chip->amp_gpio = chip->quirk->amp_gpio;
+	else if (chip->allegro_flag)
+		chip->amp_gpio = GPO_EXT_AMP_ALLEGRO;
+	else /* presumably this is for all 'maestro3's.. */
+		chip->amp_gpio = GPO_EXT_AMP_M3;
+
 	chip->num_substreams = NR_DSPS;
 	chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL);
 	if (chip->substreams == NULL) {

===================================================================


This BitKeeper patch contains the following changesets:
1.644
## Wrapped with gzip_uu ##


begin 664 bkpatch22803
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
-2U90_0.B1CD`J5@`````
`
end
