summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c141
-rw-r--r--sound/pci/hda/hda_priv.h11
2 files changed, 98 insertions, 54 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index ebbeefe203fd..fa3a04c7771e 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 0a56e8e18a5a..10bcec127319 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 {
OpenPOWER on IntegriCloud