diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index ebbeefe..fa3a04c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -297,7 +297,10 @@ static char *driver_short_names[] = {
 };
 
 /* for pcm support */
-#define get_azx_dev(substream) (substream->runtime->private_data)
+static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
+{
+	return substream->runtime->private_data;
+}
 
 #ifdef CONFIG_X86
 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
@@ -366,15 +369,11 @@ static int azx_alloc_cmd_io(struct azx *chip)
 	int err;
 
 	/* single page (at least 4096 bytes) must suffice for both ringbuffes */
-	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-				  chip->card->dev,
-				  PAGE_SIZE, &chip->rb);
-	if (err < 0) {
+	err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV,
+					 PAGE_SIZE, &chip->rb);
+	if (err < 0)
 		dev_err(chip->card->dev, "cannot allocate CORB/RIRB\n");
-		return err;
-	}
-	mark_pages_wc(chip, &chip->rb, true);
-	return 0;
+	return err;
 }
 
 static void azx_init_cmd_io(struct azx *chip)
@@ -1716,26 +1715,18 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
 {
 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	struct azx *chip = apcm->chip;
-	struct azx_dev *azx_dev = get_azx_dev(substream);
 	int ret;
 
-	dsp_lock(azx_dev);
-	if (dsp_is_locked(azx_dev)) {
+	dsp_lock(get_azx_dev(substream));
+	if (dsp_is_locked(get_azx_dev(substream))) {
 		ret = -EBUSY;
 		goto unlock;
 	}
 
-	mark_runtime_wc(chip, azx_dev, substream, false);
-	azx_dev->bufsize = 0;
-	azx_dev->period_bytes = 0;
-	azx_dev->format_val = 0;
-	ret = snd_pcm_lib_malloc_pages(substream,
-					params_buffer_bytes(hw_params));
-	if (ret < 0)
-		goto unlock;
-	mark_runtime_wc(chip, azx_dev, substream, true);
- unlock:
-	dsp_unlock(azx_dev);
+	ret = chip->ops->substream_alloc_pages(chip, substream,
+					       params_buffer_bytes(hw_params));
+unlock:
+	dsp_unlock(get_azx_dev(substream));
 	return ret;
 }
 
@@ -1745,6 +1736,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	struct azx *chip = apcm->chip;
 	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+	int err;
 
 	/* reset BDL address */
 	dsp_lock(azx_dev);
@@ -1759,10 +1751,10 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
 
 	snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
 
-	mark_runtime_wc(chip, azx_dev, substream, false);
+	err = chip->ops->substream_free_pages(chip, substream);
 	azx_dev->prepared = 0;
 	dsp_unlock(azx_dev);
-	return snd_pcm_lib_free_pages(substream);
+	return err;
 }
 
 static int azx_pcm_prepare(struct snd_pcm_substream *substream)
@@ -2398,13 +2390,11 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
 	azx_dev->locked = 1;
 	spin_unlock_irq(&chip->reg_lock);
 
-	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG,
-				  chip->card->dev,
-				  byte_size, bufp);
+	err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV_SG,
+					 byte_size, bufp);
 	if (err < 0)
 		goto err_alloc;
 
-	mark_pages_wc(chip, bufp, true);
 	azx_dev->bufsize = byte_size;
 	azx_dev->period_bytes = byte_size;
 	azx_dev->format_val = format;
@@ -2426,8 +2416,7 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
 	return azx_dev->stream_tag;
 
  error:
-	mark_pages_wc(chip, bufp, false);
-	snd_dma_free_pages(bufp);
+	chip->ops->dma_free_pages(chip, bufp);
  err_alloc:
 	spin_lock_irq(&chip->reg_lock);
 	if (azx_dev->opened)
@@ -2469,8 +2458,7 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
 	azx_dev->period_bytes = 0;
 	azx_dev->format_val = 0;
 
-	mark_pages_wc(chip, dmab, false);
-	snd_dma_free_pages(dmab);
+	chip->ops->dma_free_pages(chip, dmab);
 	dmab->area = NULL;
 
 	spin_lock_irq(&chip->reg_lock);
@@ -2879,19 +2867,14 @@ static int azx_free(struct azx *chip)
 
 	if (chip->azx_dev) {
 		for (i = 0; i < chip->num_streams; i++)
-			if (chip->azx_dev[i].bdl.area) {
-				mark_pages_wc(chip, &chip->azx_dev[i].bdl, false);
-				snd_dma_free_pages(&chip->azx_dev[i].bdl);
-			}
-	}
-	if (chip->rb.area) {
-		mark_pages_wc(chip, &chip->rb, false);
-		snd_dma_free_pages(&chip->rb);
-	}
-	if (chip->posbuf.area) {
-		mark_pages_wc(chip, &chip->posbuf, false);
-		snd_dma_free_pages(&chip->posbuf);
-	}
+			if (chip->azx_dev[i].bdl.area)
+				chip->ops->dma_free_pages(
+					chip, &chip->azx_dev[i].bdl);
+	}
+	if (chip->rb.area)
+		chip->ops->dma_free_pages(chip, &chip->rb);
+	if (chip->posbuf.area)
+		chip->ops->dma_free_pages(chip, &chip->posbuf);
 	if (chip->region_requested)
 		pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
@@ -3343,24 +3326,21 @@ static int azx_first_init(struct azx *chip)
 	for (i = 0; i < chip->num_streams; i++) {
 		dsp_lock_init(&chip->azx_dev[i]);
 		/* allocate memory for the BDL for each stream */
-		err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-					  chip->card->dev,
-					  BDL_SIZE, &chip->azx_dev[i].bdl);
+		err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV,
+						 BDL_SIZE,
+						 &chip->azx_dev[i].bdl);
 		if (err < 0) {
 			dev_err(card->dev, "cannot allocate BDL\n");
 			return -ENOMEM;
 		}
-		mark_pages_wc(chip, &chip->azx_dev[i].bdl, true);
 	}
 	/* allocate memory for the position buffer */
-	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-				  chip->card->dev,
-				  chip->num_streams * 8, &chip->posbuf);
+	err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV,
+					 chip->num_streams * 8, &chip->posbuf);
 	if (err < 0) {
 		dev_err(card->dev, "cannot allocate posbuf\n");
 		return -ENOMEM;
 	}
-	mark_pages_wc(chip, &chip->posbuf, true);
 	/* allocate CORB/RIRB */
 	err = azx_alloc_cmd_io(chip);
 	if (err < 0)
@@ -3479,6 +3459,55 @@ static int disable_msi_reset_irq(struct azx *chip)
 	return 0;
 }
 
+/* DMA page allocation helpers.  */
+static int dma_alloc_pages(struct azx *chip,
+			   int type,
+			   size_t size,
+			   struct snd_dma_buffer *buf)
+{
+	int err;
+
+	err = snd_dma_alloc_pages(type,
+				  chip->card->dev,
+				  size, buf);
+	if (err < 0)
+		return err;
+	mark_pages_wc(chip, buf, true);
+	return 0;
+}
+
+static void dma_free_pages(struct azx *chip, struct snd_dma_buffer *buf)
+{
+	mark_pages_wc(chip, buf, false);
+	snd_dma_free_pages(buf);
+}
+
+static int substream_alloc_pages(struct azx *chip,
+				 struct snd_pcm_substream *substream,
+				 size_t size)
+{
+	struct azx_dev *azx_dev = get_azx_dev(substream);
+	int ret;
+
+	mark_runtime_wc(chip, azx_dev, substream, false);
+	azx_dev->bufsize = 0;
+	azx_dev->period_bytes = 0;
+	azx_dev->format_val = 0;
+	ret = snd_pcm_lib_malloc_pages(substream, size);
+	if (ret < 0)
+		return ret;
+	mark_runtime_wc(chip, azx_dev, substream, true);
+	return 0;
+}
+
+static int substream_free_pages(struct azx *chip,
+				struct snd_pcm_substream *substream)
+{
+	struct azx_dev *azx_dev = get_azx_dev(substream);
+	mark_runtime_wc(chip, azx_dev, substream, false);
+	return snd_pcm_lib_free_pages(substream);
+}
+
 static const struct hda_controller_ops pci_hda_ops = {
 	.writel = pci_azx_writel,
 	.readl = pci_azx_readl,
@@ -3487,6 +3516,10 @@ static const struct hda_controller_ops pci_hda_ops = {
 	.writeb = pci_azx_writeb,
 	.readb = pci_azx_readb,
 	.disable_msi_reset_irq = disable_msi_reset_irq,
+	.dma_alloc_pages = dma_alloc_pages,
+	.dma_free_pages = dma_free_pages,
+	.substream_alloc_pages = substream_alloc_pages,
+	.substream_free_pages = substream_free_pages,
 };
 
 static int azx_probe(struct pci_dev *pci,
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h
index 0a56e8e..10bcec1 100644
--- a/sound/pci/hda/hda_priv.h
+++ b/sound/pci/hda/hda_priv.h
@@ -298,6 +298,17 @@ struct hda_controller_ops {
 	u8 (*readb)(u8 *addr);
 	/* Disable msi if supported, PCI only */
 	int (*disable_msi_reset_irq)(struct azx *);
+	/* Allocation ops */
+	int (*dma_alloc_pages)(struct azx *chip,
+			       int type,
+			       size_t size,
+			       struct snd_dma_buffer *buf);
+	void (*dma_free_pages)(struct azx *chip, struct snd_dma_buffer *buf);
+	int (*substream_alloc_pages)(struct azx *chip,
+				     struct snd_pcm_substream *substream,
+				     size_t size);
+	int (*substream_free_pages)(struct azx *chip,
+				    struct snd_pcm_substream *substream);
 };
 
 struct azx_pcm {
