[PATCHv6 9/9] drm: tegra: Add gr2d device
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/drm.c | 239 +- drivers/gpu/host1x/drm/drm.h | 28 +++- drivers/gpu/host1x/drm/gr2d.c | 325 + drivers/gpu/host1x/host1x.h |3 +- include/drm/tegra_drm.h | 131 + 7 files changed, 730 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/host1x/drm/gr2d.c create mode 100644 include/drm/tegra_drm.h diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index d1d7e35..d90168f 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -17,4 +17,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/cma.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 6af8081..0091632 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -211,11 +211,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: @@ -228,6 +234,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/drm.c b/drivers/gpu/host1x/drm/drm.c index dbd4808..1f0754a 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 @@ -8,13 +8,17 @@ */ #include +#include #include #include #include #include +#include "cma.h" +#include "dev.h" #include "drm.h" #include "host1x_client.h" +#include "syncpt.h" #define DRIVER_NAME "tegra" #define DRIVER_DESC "NVIDIA Tegra graphics" @@ -77,8 +81,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; @@ -273,9 +279,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; @@ -283,7 +304,214 @@ static void tegra_drm_lastclose(struct drm_device *drm) drm_fbdev_cma_restore_mode(host1x->fbdev); } +static int tegra_drm_ioctl_syncpt_read(struct drm_device *drm, void *data, + struct drm_file *file_priv) +{ + struct tegra_drm_syncpt_read_args *args = data; + struct host1x *host = host1x_get_host(drm->dev); + struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id); + + if (!sp) + return -EINVAL; + + args->value = host1x_syncpt_read_min(sp); + return 0; +} + +static int tegra_drm_ioctl_syncpt_incr(struct drm_device *drm, void *data, + struct drm_file *file_priv) +{ + struct tegra_drm_syncpt_incr_args *args = data; + struct host1x *host = host1x_get_host(drm->dev); + struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id); + + if (!sp) +
[PATCHv6 9/9] drm: tegra: Add gr2d device
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/drm.c | 239 +- drivers/gpu/host1x/drm/drm.h | 28 +++- drivers/gpu/host1x/drm/gr2d.c | 325 + drivers/gpu/host1x/host1x.h |3 +- include/drm/tegra_drm.h | 131 + 7 files changed, 730 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/host1x/drm/gr2d.c create mode 100644 include/drm/tegra_drm.h diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index d1d7e35..d90168f 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -17,4 +17,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/cma.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 6af8081..0091632 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -211,11 +211,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: @@ -228,6 +234,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/drm.c b/drivers/gpu/host1x/drm/drm.c index dbd4808..1f0754a 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 @@ -8,13 +8,17 @@ */ #include +#include #include #include #include #include +#include "cma.h" +#include "dev.h" #include "drm.h" #include "host1x_client.h" +#include "syncpt.h" #define DRIVER_NAME "tegra" #define DRIVER_DESC "NVIDIA Tegra graphics" @@ -77,8 +81,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; @@ -273,9 +279,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; @@ -283,7 +304,214 @@ static void tegra_drm_lastclose(struct drm_device *drm) drm_fbdev_cma_restore_mode(host1x->fbdev); } +static int tegra_drm_ioctl_syncpt_read(struct drm_device *drm, void *data, + struct drm_file *file_priv) +{ + struct tegra_drm_syncpt_read_args *args = data; + struct host1x *host = host1x_get_host(drm->dev); + struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id); + + if (!sp) + return -EINVAL; + + args->value = host1x_syncpt_read_min(sp); + return 0; +} + +static int tegra_drm_ioctl_syncpt_incr(struct drm_device *drm, void *data, + struct drm_file *file_priv) +{ + struct tegra_drm_syncpt_incr_args *args = data; + struct host1x *host = host1x_get_host(drm->dev); + struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id); + + if (!sp)