summaryrefslogtreecommitdiff
path: root/bridge/dmm_buffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'bridge/dmm_buffer.h')
-rw-r--r--bridge/dmm_buffer.h171
1 files changed, 171 insertions, 0 deletions
diff --git a/bridge/dmm_buffer.h b/bridge/dmm_buffer.h
new file mode 100644
index 0000000..f86df7e
--- /dev/null
+++ b/bridge/dmm_buffer.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Authors:
+ * Felipe Contreras <felipe.contreras@nokia.com>
+ * Marco Ballesio <marco.ballesio@nokia.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in LICENSE included in the
+ * packaging of this file.
+ */
+
+#ifndef DMM_BUFFER_H
+#define DMM_BUFFER_H
+
+#include <stdlib.h> /* for calloc, free */
+#include <string.h> /* for memset */
+
+#include "dsp_bridge.h"
+#include "log.h"
+
+#define ROUND_UP(num, scale) (((num) + ((scale) - 1)) & ~((scale) - 1))
+#define PAGE_SIZE 0x1000
+
+enum dma_data_direction {
+ DMA_BIDIRECTIONAL,
+ DMA_TO_DEVICE,
+ DMA_FROM_DEVICE,
+};
+
+typedef struct {
+ int handle;
+ void *proc;
+ void *data;
+ void *allocated_data;
+ size_t size;
+ size_t len;
+ void *reserve;
+ void *map;
+ bool need_copy;
+ size_t alignment;
+ void *user_data;
+ bool used;
+ bool keyframe;
+ int dir;
+} dmm_buffer_t;
+
+static inline dmm_buffer_t *
+dmm_buffer_new(int handle,
+ void *proc,
+ int dir)
+{
+ dmm_buffer_t *b;
+ b = calloc(1, sizeof(*b));
+
+ pr_debug("%p", b);
+ b->handle = handle;
+ b->proc = proc;
+ b->alignment = 128;
+ b->dir = dir;
+
+ return b;
+}
+
+static inline void
+dmm_buffer_free(dmm_buffer_t *b)
+{
+ pr_debug("%p", b);
+ if (!b)
+ return;
+ if (b->map)
+ dsp_unmap(b->handle, b->proc, b->map);
+ if (b->reserve)
+ dsp_unreserve(b->handle, b->proc, b->reserve);
+ free(b->allocated_data);
+ free(b);
+}
+
+static inline void
+dmm_buffer_begin(dmm_buffer_t *b,
+ size_t len)
+{
+ pr_debug("%p", b);
+ if (b->dir == DMA_FROM_DEVICE)
+ dsp_invalidate(b->handle, b->proc, b->data, len);
+ else
+ dsp_flush(b->handle, b->proc, b->data, len, 1);
+}
+
+static inline void
+dmm_buffer_end(dmm_buffer_t *b,
+ size_t len)
+{
+ pr_debug("%p", b);
+ if (b->dir != DMA_TO_DEVICE)
+ dsp_invalidate(b->handle, b->proc, b->data, len);
+}
+
+static inline int
+dmm_buffer_map(dmm_buffer_t *b)
+{
+ size_t to_reserve;
+ pr_debug("%p", b);
+ if (b->map)
+ dsp_unmap(b->handle, b->proc, b->map);
+ if (b->reserve)
+ dsp_unreserve(b->handle, b->proc, b->reserve);
+ /**
+ * @todo What exactly do we want to do here? Shouldn't the driver
+ * calculate this?
+ */
+ to_reserve = ROUND_UP(b->size, PAGE_SIZE) + PAGE_SIZE;
+ dsp_reserve(b->handle, b->proc, to_reserve, &b->reserve);
+ return dsp_map(b->handle, b->proc, b->data, b->size, b->reserve, &b->map, 0);
+}
+
+static inline void
+dmm_buffer_unmap(dmm_buffer_t *b)
+{
+ pr_debug("%p", b);
+ if (b->map) {
+ dsp_unmap(b->handle, b->proc, b->map);
+ b->map = NULL;
+ }
+ if (b->reserve) {
+ dsp_unreserve(b->handle, b->proc, b->reserve);
+ b->reserve = NULL;
+ }
+}
+
+static inline void
+dmm_buffer_allocate(dmm_buffer_t *b,
+ size_t size)
+{
+ pr_debug("%p", b);
+ free(b->allocated_data);
+ if (b->alignment != 0) {
+ if (posix_memalign(&b->allocated_data, b->alignment, ROUND_UP(size, b->alignment)) != 0)
+ b->allocated_data = NULL;
+ b->data = b->allocated_data;
+ }
+ else
+ b->data = b->allocated_data = malloc(size);
+ b->size = size;
+}
+
+static inline void
+dmm_buffer_use(dmm_buffer_t *b,
+ void *data,
+ size_t size)
+{
+ pr_debug("%p", b);
+ b->data = data;
+ b->size = size;
+}
+
+static inline dmm_buffer_t *
+dmm_buffer_calloc(int handle,
+ void *proc,
+ size_t size,
+ int dir)
+{
+ dmm_buffer_t *tmp;
+ tmp = dmm_buffer_new(handle, proc, dir);
+ dmm_buffer_allocate(tmp, size);
+ memset(tmp->data, 0, size);
+ return tmp;
+}
+
+#endif /* DMM_BUFFER_H */