diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index fd4cf7d6eb3f..0931b1e65e56 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -838,7 +838,18 @@ SUB_REG(FXIDX, IDX,		0x0000ffff)
 #define A_SPRA			0x6b		/* S/PDIF Host Record Address			*/
 #define A_SPRC			0x6c		/* S/PDIF Host Record Control			*/
 
+// NOTE: 64-bit
+// Voice 0 holds the counter, while voice 1 holds the enable bits.
+// Bits in IPR are set according to incoming IRQs as usual.
+// When a corresponding bit is set in the delay enable register,
+// the counter starts, and the IRQ isn't delivered until timeout.
+// Additional delayed IRQs arriving during the countdown do not
+// retrigger it, so they will be delayed less or not at all.
+// Non-delayed IRQs arriving during the countdown are delivered
+// immediately, while the countdown continues.
 #define A_DICE			0x6d		/* Delayed Interrupt Counter & Enable		*/
+#define A_DICE_DELAY_MASK	0x000003ff	/* Interrupt delay minus 1			*/
+#define A_DICE_COUNTER_MASK	0x03ff0000	/* Counter's current value			*/
 
 #define A_TTB			0x6e		/* Tank Table Base				*/
 #define A_TDOF			0x6f		/* Tank Delay Offset				*/
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 2125925c2d5e..97a4be6eaf7a 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -159,6 +159,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir)
 		/* disable channel interrupt */
 		CLIEL, 0,
 		CLIEH, 0,
+		HLIEL, 0,
+		HLIEH, 0,
 
 		/* disable stop on loop end */
 		SOLEL, 0,
@@ -174,6 +176,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir)
 				      AC97SLOT_REAR_LEFT);
 	}
 
+	if (emu->das_mode) {
+		// Enable delayed period interrupts
+		snd_emu10k1_ptr_write(emu, A_DICE, 0, 64 - 3 + 1);
+		snd_emu10k1_ptr_write(emu, A_DICE, 1, IPR_CHANNELLOOP);
+	}
+
 	/* init envelope engine */
 	for (ch = 0; ch < NUM_G; ch++)
 		snd_emu10k1_voice_init(emu, ch);
@@ -414,6 +422,12 @@ int snd_emu10k1_done(struct snd_emu10k1 *emu)
 	else
 		snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP);
 
+	if (emu->das_mode) {
+		// Disable delayed period interrupts
+		snd_emu10k1_ptr_write(emu, A_DICE, 0, 0);
+		snd_emu10k1_ptr_write(emu, A_DICE, 1, 0);
+	}
+
 	snd_emu10k1_ptr_write_multiple(emu, 0,
 		/* reset recording buffers */
 		MICBS, 0,
@@ -429,6 +443,8 @@ int snd_emu10k1_done(struct snd_emu10k1 *emu)
 		/* disable channel interrupt */
 		CLIEL, 0,
 		CLIEH, 0,
+		HLIEL, 0,
+		HLIEH, 0,
 		SOLEL, 0,
 		SOLEH, 0,
 
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index ccb0e13da3dd..b7841076f019 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -96,7 +96,9 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm *epcm,
 	if (err < 0)
 		return err;
 
-	if (epcm->extra == NULL) {
+	if (epcm->emu->das_mode) {
+		epcm->voices[0]->interrupt = snd_emu10k1_pcm_interrupt;
+	} else if (epcm->extra == NULL) {
 		// The hardware supports only (half-)loop interrupts, so to support an
 		// arbitrary number of periods per buffer, we use an extra voice with a
 		// period-sized loop as the interrupt source. Additionally, the interrupt
@@ -500,13 +502,8 @@ static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream)
 	epcm->pitch_target = PITCH_48000;
 
 	start_addr = epcm->start_addr >> 1;  // 16-bit voices
-
-	extra_size = runtime->period_size >> shift;
 	channel_size = runtime->buffer_size >> shift;
 
-	snd_emu10k1_pcm_init_extra_voice(emu, epcm->extra, true,
-					 start_addr, start_addr + extra_size);
-
 	if (das_mode) {
 		unsigned count = 1 << shift;
 		start_addr >>= 1;
@@ -520,6 +517,10 @@ static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream)
 			}
 		}
 	} else {
+		extra_size = runtime->period_size >> shift;
+		snd_emu10k1_pcm_init_extra_voice(emu, epcm->extra, true,
+						 start_addr, start_addr + extra_size);
+
 		epcm->ccca_start_addr = start_addr;
 		for (i = 0; i < runtime->channels; i++) {
 			snd_emu10k1_pcm_init_voices(emu, epcm->voices[i], true, false,
@@ -547,7 +548,7 @@ static const struct snd_pcm_hardware snd_emu10k1_efx_playback =
 	.buffer_bytes_max =	(128*1024),
 	.period_bytes_max =	(128*1024),
 	.periods_min =		2,
-	.periods_max =		1024,
+	.periods_max =		2,
 	.fifo_size =		0,
 };
 
@@ -698,8 +699,16 @@ static void snd_emu10k1_playback_prepare_voices(struct snd_emu10k1 *emu,
 	// This is why all other (open) drivers for these chips use timer-based
 	// interrupts.
 	//
-	eloop_start += (epcm->resume_pos + eloop_size - 3) % eloop_size;
-	snd_emu10k1_ptr_write(emu, CCCA_CURRADDR, epcm->extra->number, eloop_start);
+	// But then, Audigy introduced delayed interrupt functionality, so we
+	// use it in D.A.S. mode, where we may need all voices. We can't use
+	// it in regular mode due to supporting multiple substreams, which the
+	// delayed IRQs cannot really handle; also, we prefer supporting an
+	// arbitrary number of periods there, for which we need the extra voice.
+	//
+	if (!emu->das_mode) {
+		eloop_start += (epcm->resume_pos + eloop_size - 3) % eloop_size;
+		snd_emu10k1_ptr_write(emu, CCCA_CURRADDR, epcm->extra->number, eloop_start);
+	}
 
 	// It takes a moment until the cache fills complete,
 	// but the unmuting takes long enough for that.
@@ -793,13 +802,25 @@ static void snd_emu10k1_playback_set_running(struct snd_emu10k1 *emu,
 					     struct snd_emu10k1_pcm *epcm)
 {
 	epcm->running = 1;
-	snd_emu10k1_voice_intr_enable(emu, epcm->extra->number);
+	if (emu->das_mode) {
+		unsigned int voice = epcm->voices[0]->number;
+		snd_emu10k1_voice_half_loop_intr_enable(emu, voice);
+		snd_emu10k1_voice_intr_enable(emu, voice);
+	} else {
+		snd_emu10k1_voice_intr_enable(emu, epcm->extra->number);
+	}
 }
 
 static void snd_emu10k1_playback_set_stopped(struct snd_emu10k1 *emu,
 					      struct snd_emu10k1_pcm *epcm)
 {
-	snd_emu10k1_voice_intr_disable(emu, epcm->extra->number);
+	if (emu->das_mode) {
+		unsigned int voice = epcm->voices[0]->number;
+		snd_emu10k1_voice_half_loop_intr_disable(emu, voice);
+		snd_emu10k1_voice_intr_disable(emu, voice);
+	} else {
+		snd_emu10k1_voice_intr_disable(emu, epcm->extra->number);
+	}
 	epcm->running = 0;
 }
 
@@ -1064,7 +1085,8 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
 			result = snd_emu10k1_voice_clear_loop_stop_multiple_atomic(emu, mask);
 			if (result == 0) {
 				// The extra voice is allowed to lag a bit
-				snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
+				if (!emu->das_mode)
+					snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
 				goto leave;
 			}
 
@@ -1080,7 +1102,8 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		snd_emu10k1_playback_stop_voice(emu, epcm->extra);
+		if (!emu->das_mode)
+			snd_emu10k1_playback_stop_voice(emu, epcm->extra);
 		snd_emu10k1_efx_playback_stop_voices(
 				emu, epcm, das_mode, count, runtime->channels);
 
@@ -1428,15 +1451,16 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
 					SNDRV_PCM_INFO_RESUME |
 					SNDRV_PCM_INFO_PAUSE;
 				if (shift == 2)
-					runtime->hw.channels_max = 7;  // FIXME: should be 8, but extra voice ...
+					runtime->hw.channels_max = 8;
 				err = snd_pcm_hw_constraint_step(
 						runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1 << shift);
 				if (err < 0) {
 					kfree(epcm);
 					return err;
 				}
 			}
 			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			runtime->hw.periods_max = 2;  // Not using an extra voice
 		}
 	}
 	err = snd_emu10k1_playback_set_constraints(emu, runtime);
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index 71aa90b9cc88..be2dbed12e74 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -23,6 +23,14 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id)
 				 "Suspected sound card removal\n");
 			break;
 		}
+		if ((status & IPR_CHANNELLOOP) && emu->das_mode &&
+		    (snd_emu10k1_ptr_read(emu, A_DICE, 0) & A_DICE_COUNTER_MASK)) {
+			// If another IRQ "punched through" the delay,
+			// we mask away the delayed IRQ.
+			status &= ~(IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK);
+			if (!status)  // Will usually happen in 2nd iteration
+				break;
+		}
 		if (++timeout == 1000) {
 			dev_info(emu->card->dev, "emu10k1 irq routine failure\n");
 			break;
