@@ -294,6 +294,9 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
void (*ack)(struct hdac_bus *,
struct hdac_stream *));
+int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus);
+void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
+
/*
* HD-audio stream
*/
@@ -401,3 +401,47 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
}
}
EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq);
+
+int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
+{
+ struct hdac_stream *hstream;
+ int num_streams = 0;
+ int err;
+
+ list_for_each_entry(hstream, &bus->stream_list, list) {
+ dsp_lock_init(&hstream);
+ /* allocate memory for the BDL for each stream */
+ err = bus->ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV,
+ BDL_SIZE,
+ &hstream->bdl);
+ num_streams++;
+ if (err < 0)
+ return -ENOMEM;
+ }
+ /* allocate memory for the position buffer */
+ err = bus->ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV,
+ num_streams * 8, &bus->posbuf);
+ if (err < 0)
+ return -ENOMEM;
+
+ /* single page (at least 4096 bytes) must suffice for both ringbuffes */
+ return bus->ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV,
+ PAGE_SIZE, &bus->rb);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages);
+
+void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
+{
+ struct hdac_stream *hstream;
+
+ list_for_each_entry(hstream, &bus->stream_list, list) {
+ if (hstream->bdl.area)
+ bus->ops->dma_free_pages(
+ bus, &hstream->bdl);
+ }
+ if (bus->rb.area)
+ bus->ops->dma_free_pages(bus, &bus->rb);
+ if (bus->posbuf.area)
+ bus->ops->dma_free_pages(bus, &bus->posbuf);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);