[PATCHv9 9/9] drm: tegra: Add gr2d device

2013-03-22 Thread Terje Bergstrom
Add client driver for 2D device, and IOCTLs to pass work to host1x
channel for 2D.

Also adds functions that can be called to access sync points from
DRM.

Signed-off-by: Arto Merilainen 
Signed-off-by: Terje Bergstrom 
---
 drivers/gpu/host1x/Makefile|1 +
 drivers/gpu/host1x/dev.c   |7 +
 drivers/gpu/host1x/drm/Kconfig |9 ++
 drivers/gpu/host1x/drm/drm.c   |  212 -
 drivers/gpu/host1x/drm/drm.h   |   27 +++-
 drivers/gpu/host1x/drm/gr2d.c  |  339 
 drivers/gpu/host1x/host1x.h|4 +-
 include/uapi/drm/Kbuild|1 +
 include/uapi/drm/tegra_drm.h   |  136 
 9 files changed, 733 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/host1x/drm/gr2d.c
 create mode 100644 include/uapi/drm/tegra_drm.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 3768dbc..3b037b6 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -16,4 +16,5 @@ ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
 host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
+host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 8ce9889..28e28a2 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -209,11 +209,17 @@ static int __init tegra_host1x_init(void)
err = platform_driver_register(_hdmi_driver);
if (err < 0)
goto unregister_dc;
+
+   err = platform_driver_register(_gr2d_driver);
+   if (err < 0)
+   goto unregister_hdmi;
 #endif

return 0;

 #ifdef CONFIG_DRM_TEGRA
+unregister_hdmi:
+   platform_driver_unregister(_hdmi_driver);
 unregister_dc:
platform_driver_unregister(_dc_driver);
 unregister_host1x:
@@ -226,6 +232,7 @@ module_init(tegra_host1x_init);
 static void __exit tegra_host1x_exit(void)
 {
 #ifdef CONFIG_DRM_TEGRA
+   platform_driver_unregister(_gr2d_driver);
platform_driver_unregister(_hdmi_driver);
platform_driver_unregister(_dc_driver);
 #endif
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
index f743540..6e3f567 100644
--- a/drivers/gpu/host1x/drm/Kconfig
+++ b/drivers/gpu/host1x/drm/Kconfig
@@ -13,6 +13,15 @@ config DRM_TEGRA

 if DRM_TEGRA

+config DRM_TEGRA_STAGING
+   bool "Enable HOST1X interface"
+   depends on STAGING
+   default n
+   help
+ Say yes if HOST1X should be available for userspace DRM users.
+
+ If unsure, choose N.
+
 config DRM_TEGRA_DEBUG
bool "NVIDIA Tegra DRM debug support"
help
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index c4e45c1..2b561c9 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,6 +14,9 @@
 #include 
 #include 

+#include 
+#include 
+
 #include "host1x_client.h"
 #include "dev.h"
 #include "drm.h"
@@ -81,8 +84,10 @@ static int host1x_parse_dt(struct host1x_drm *host1x)
static const char * const compat[] = {
"nvidia,tegra20-dc",
"nvidia,tegra20-hdmi",
+   "nvidia,tegra20-gr2d",
"nvidia,tegra30-dc",
"nvidia,tegra30-hdmi",
+   "nvidia,tegra30-gr2d",
};
unsigned int i;
int err;
@@ -277,9 +282,24 @@ static int tegra_drm_unload(struct drm_device *drm)

 static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
 {
+   struct host1x_drm_file *fpriv;
+
+   fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+   if (!fpriv)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(>contexts);
+   filp->driver_priv = fpriv;
+
return 0;
 }

+static void host1x_drm_context_free(struct host1x_drm_context *context)
+{
+   context->client->ops->close_channel(context);
+   kfree(context);
+}
+
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
struct host1x_drm *host1x = drm->dev_private;
@@ -287,7 +307,190 @@ static void tegra_drm_lastclose(struct drm_device *drm)
tegra_fbdev_restore_mode(host1x->fbdev);
 }

+#ifdef CONFIG_DRM_TEGRA_STAGING
+static bool host1x_drm_file_owns_context(struct host1x_drm_file *file,
+struct host1x_drm_context *context)
+{
+   struct host1x_drm_context *ctx;
+
+   list_for_each_entry(ctx, >contexts, list)
+   if (ctx == context)
+   return true;
+
+   return 

[PATCHv9 9/9] drm: tegra: Add gr2d device

2013-03-22 Thread Terje Bergstrom
Add client driver for 2D device, and IOCTLs to pass work to host1x
channel for 2D.

Also adds functions that can be called to access sync points from
DRM.

Signed-off-by: Arto Merilainen amerilai...@nvidia.com
Signed-off-by: Terje Bergstrom tbergst...@nvidia.com
---
 drivers/gpu/host1x/Makefile|1 +
 drivers/gpu/host1x/dev.c   |7 +
 drivers/gpu/host1x/drm/Kconfig |9 ++
 drivers/gpu/host1x/drm/drm.c   |  212 -
 drivers/gpu/host1x/drm/drm.h   |   27 +++-
 drivers/gpu/host1x/drm/gr2d.c  |  339 
 drivers/gpu/host1x/host1x.h|4 +-
 include/uapi/drm/Kbuild|1 +
 include/uapi/drm/tegra_drm.h   |  136 
 9 files changed, 733 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/host1x/drm/gr2d.c
 create mode 100644 include/uapi/drm/tegra_drm.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 3768dbc..3b037b6 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -16,4 +16,5 @@ ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
 host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
 host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
+host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 8ce9889..28e28a2 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -209,11 +209,17 @@ static int __init tegra_host1x_init(void)
err = platform_driver_register(tegra_hdmi_driver);
if (err  0)
goto unregister_dc;
+
+   err = platform_driver_register(tegra_gr2d_driver);
+   if (err  0)
+   goto unregister_hdmi;
 #endif
 
return 0;
 
 #ifdef CONFIG_DRM_TEGRA
+unregister_hdmi:
+   platform_driver_unregister(tegra_hdmi_driver);
 unregister_dc:
platform_driver_unregister(tegra_dc_driver);
 unregister_host1x:
@@ -226,6 +232,7 @@ module_init(tegra_host1x_init);
 static void __exit tegra_host1x_exit(void)
 {
 #ifdef CONFIG_DRM_TEGRA
+   platform_driver_unregister(tegra_gr2d_driver);
platform_driver_unregister(tegra_hdmi_driver);
platform_driver_unregister(tegra_dc_driver);
 #endif
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
index f743540..6e3f567 100644
--- a/drivers/gpu/host1x/drm/Kconfig
+++ b/drivers/gpu/host1x/drm/Kconfig
@@ -13,6 +13,15 @@ config DRM_TEGRA
 
 if DRM_TEGRA
 
+config DRM_TEGRA_STAGING
+   bool Enable HOST1X interface
+   depends on STAGING
+   default n
+   help
+ Say yes if HOST1X should be available for userspace DRM users.
+
+ If unsure, choose N.
+
 config DRM_TEGRA_DEBUG
bool NVIDIA Tegra DRM debug support
help
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index c4e45c1..2b561c9 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,6 +14,9 @@
 #include linux/dma-mapping.h
 #include asm/dma-iommu.h
 
+#include drm/drm.h
+#include drm/drmP.h
+
 #include host1x_client.h
 #include dev.h
 #include drm.h
@@ -81,8 +84,10 @@ static int host1x_parse_dt(struct host1x_drm *host1x)
static const char * const compat[] = {
nvidia,tegra20-dc,
nvidia,tegra20-hdmi,
+   nvidia,tegra20-gr2d,
nvidia,tegra30-dc,
nvidia,tegra30-hdmi,
+   nvidia,tegra30-gr2d,
};
unsigned int i;
int err;
@@ -277,9 +282,24 @@ static int tegra_drm_unload(struct drm_device *drm)
 
 static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
 {
+   struct host1x_drm_file *fpriv;
+
+   fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+   if (!fpriv)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(fpriv-contexts);
+   filp-driver_priv = fpriv;
+
return 0;
 }
 
+static void host1x_drm_context_free(struct host1x_drm_context *context)
+{
+   context-client-ops-close_channel(context);
+   kfree(context);
+}
+
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
struct host1x_drm *host1x = drm-dev_private;
@@ -287,7 +307,190 @@ static void tegra_drm_lastclose(struct drm_device *drm)
tegra_fbdev_restore_mode(host1x-fbdev);
 }
 
+#ifdef CONFIG_DRM_TEGRA_STAGING
+static bool host1x_drm_file_owns_context(struct host1x_drm_file *file,
+struct host1x_drm_context *context)
+{
+   struct host1x_drm_context *ctx;
+
+