summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInki Dae <inki.dae@samsung.com>2013-08-20 17:39:12 +0900
committerChanho Park <chanho61.park@samsung.com>2014-03-20 17:34:49 +0900
commiteee839f9d44c26b0aed9ba23a708bb0a999618c3 (patch)
treededf8b1c63a3c052d5722819c02212419c5ad8a0
parent29041aeeefffe8c2afcae303047c8a01878540e7 (diff)
downloadlinux-3.10-eee839f9d44c26b0aed9ba23a708bb0a999618c3.tar.gz
linux-3.10-eee839f9d44c26b0aed9ba23a708bb0a999618c3.tar.bz2
linux-3.10-eee839f9d44c26b0aed9ba23a708bb0a999618c3.zip
drm/exynos: add dmabuf sync support for g2d driver
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index ce28fc9256f..90432d3ff77 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -19,6 +19,7 @@
#include <linux/dma-mapping.h>
#include <linux/dma-attrs.h>
#include <linux/of.h>
+#include <linux/dmabuf-sync.h>
#include <drm/drmP.h>
#include <drm/exynos_drm.h>
@@ -205,6 +206,7 @@ struct g2d_cmdlist_node {
struct g2d_buf_info buf_info;
struct drm_exynos_pending_g2d_event *event;
+ struct dmabuf_sync *sync;
};
struct g2d_runqueue_node {
@@ -245,6 +247,20 @@ struct g2d_data {
unsigned long max_pool;
};
+static void g2d_dmabuf_sync_free(void *priv)
+{
+ struct g2d_cmdlist_node *node = priv;
+
+ if (!node)
+ return;
+
+ node->sync = NULL;
+}
+
+static struct dmabuf_sync_priv_ops dmabuf_sync_ops = {
+ .free = g2d_dmabuf_sync_free,
+};
+
static int g2d_init_cmdlist(struct g2d_data *g2d)
{
struct device *dev = g2d->dev;
@@ -684,6 +700,12 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
int ret;
int i;
+ if (is_dmabuf_sync_supported()) {
+ node->sync = dmabuf_sync_init("g2d", &dmabuf_sync_ops, node);
+ if (IS_ERR(node->sync))
+ node->sync = NULL;
+ }
+
for (i = 0; i < buf_info->map_nr; i++) {
struct g2d_buf_desc *buf_desc;
enum g2d_reg_type reg_type;
@@ -706,7 +728,30 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
if (buf_info->types[reg_type] == BUF_TYPE_GEM) {
unsigned long size;
+ unsigned int type;
+ void *dma_buf = NULL;
+
+ if (!node->sync)
+ goto out_dmabuf_sync;
+
+ dma_buf = exynos_drm_gem_get_dmabuf(drm_dev, handle,
+ file);
+ if (!dma_buf)
+ goto out_dmabuf_sync;
+
+ if (reg_type == REG_TYPE_DST_PLANE2 ||
+ reg_type == REG_TYPE_DST)
+ type = DMA_BUF_ACCESS_DMA_W;
+ else
+ type = DMA_BUF_ACCESS_DMA_R;
+
+ ret = dmabuf_sync_get(node->sync, dma_buf, type);
+ if (ret < 0) {
+ WARN_ON(1);
+ dmabuf_sync_put_all(node->sync);
+ }
+out_dmabuf_sync:
size = exynos_drm_gem_get_size(drm_dev, handle, file);
if (!size) {
ret = -EFAULT;
@@ -756,9 +801,19 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
buf_info->handles[reg_type] = handle;
}
- return 0;
+ if (node->sync) {
+ if (list_empty(&node->sync->syncs))
+ dmabuf_sync_fini(node->sync);
+ }
+
+ return ret;
err:
+ if (node->sync) {
+ dmabuf_sync_put_all(node->sync);
+ dmabuf_sync_fini(node->sync);
+ }
+
buf_info->map_nr = i;
return ret;
}
@@ -805,6 +860,17 @@ static void g2d_dma_start(struct g2d_data *g2d,
struct g2d_cmdlist_node, list);
int ret;
+ if (node->sync) {
+ int ret;
+
+ ret = dmabuf_sync_lock(node->sync);
+ if (ret < 0) {
+ WARN_ON(1);
+ dmabuf_sync_put_all(node->sync);
+ dmabuf_sync_fini(node->sync);
+ }
+ }
+
ret = pm_runtime_get_sync(g2d->dev);
if (ret < 0)
return;
@@ -839,8 +905,22 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d,
* commands in run_cmdlist have been completed so unmap all gem
* objects in each command node so that they are unreferenced.
*/
- list_for_each_entry(node, &runqueue_node->run_cmdlist, list)
+ list_for_each_entry(node, &runqueue_node->run_cmdlist, list) {
+ if (node->sync) {
+ int ret;
+
+ ret = dmabuf_sync_unlock(node->sync);
+ if (ret < 0) {
+ WARN_ON(1);
+ /* TODO */
+ }
+
+ dmabuf_sync_put_all(node->sync);
+ dmabuf_sync_fini(node->sync);
+ }
+
g2d_unmap_cmdlist_gem(g2d, node, runqueue_node->filp);
+ }
list_splice_tail_init(&runqueue_node->run_cmdlist, &g2d->free_cmdlist);
mutex_unlock(&g2d->cmdlist_mutex);