diff options
author | Arto Merilainen <amerilainen@nvidia.com> | 2013-03-22 10:34:08 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@avionic-design.de> | 2013-04-22 06:40:04 -0400 |
commit | de2ba664c30fcdb0f678ab6cbb57e01a0b206085 (patch) | |
tree | ff5cca80336ae30f9d050305750a89332d4198a8 /drivers/gpu/host1x | |
parent | 692e6d7be8099225f04b2d97299bc03479a5fcdb (diff) |
gpu: host1x: drm: Add memory manager and fb
This patch introduces a memory manager for tegra drm and moves
existing parts to use it. As cma framebuffer helpers can no more
be used, this patch adds also a separate framebuffer driver for
tegra.
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Erik Faye-Lund <kusmabite@gmail.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r-- | drivers/gpu/host1x/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/Kconfig | 8 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/dc.c | 23 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/drm.c | 17 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/drm.h | 18 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/fb.c | 338 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/gem.c | 270 | ||||
-rw-r--r-- | drivers/gpu/host1x/drm/gem.h | 59 |
8 files changed, 700 insertions, 34 deletions
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index 9a6fc767f6b8..3768dbc27184 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile | |||
@@ -15,4 +15,5 @@ ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG | |||
15 | 15 | ||
16 | host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o | 16 | host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o |
17 | host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o | 17 | host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o |
18 | host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o | ||
18 | obj-$(CONFIG_TEGRA_HOST1X) += host1x.o | 19 | obj-$(CONFIG_TEGRA_HOST1X) += host1x.o |
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig index 33f8f7a39196..9a28901d07ce 100644 --- a/drivers/gpu/host1x/drm/Kconfig +++ b/drivers/gpu/host1x/drm/Kconfig | |||
@@ -2,11 +2,9 @@ config DRM_TEGRA | |||
2 | bool "NVIDIA Tegra DRM" | 2 | bool "NVIDIA Tegra DRM" |
3 | depends on DRM && OF | 3 | depends on DRM && OF |
4 | select DRM_KMS_HELPER | 4 | select DRM_KMS_HELPER |
5 | select DRM_GEM_CMA_HELPER | 5 | select FB_SYS_FILLRECT |
6 | select DRM_KMS_CMA_HELPER | 6 | select FB_SYS_COPYAREA |
7 | select FB_CFB_FILLRECT | 7 | select FB_SYS_IMAGEBLIT |
8 | select FB_CFB_COPYAREA | ||
9 | select FB_CFB_IMAGEBLIT | ||
10 | help | 8 | help |
11 | Choose this option if you have an NVIDIA Tegra SoC. | 9 | Choose this option if you have an NVIDIA Tegra SoC. |
12 | 10 | ||
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c index 29a79b66f36c..85ea6163a7b0 100644 --- a/drivers/gpu/host1x/drm/dc.c +++ b/drivers/gpu/host1x/drm/dc.c | |||
@@ -14,9 +14,10 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/clk/tegra.h> | 15 | #include <linux/clk/tegra.h> |
16 | 16 | ||
17 | #include "drm.h" | ||
18 | #include "dc.h" | ||
19 | #include "host1x_client.h" | 17 | #include "host1x_client.h" |
18 | #include "dc.h" | ||
19 | #include "drm.h" | ||
20 | #include "gem.h" | ||
20 | 21 | ||
21 | struct tegra_plane { | 22 | struct tegra_plane { |
22 | struct drm_plane base; | 23 | struct drm_plane base; |
@@ -52,9 +53,9 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
52 | window.bits_per_pixel = fb->bits_per_pixel; | 53 | window.bits_per_pixel = fb->bits_per_pixel; |
53 | 54 | ||
54 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { | 55 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { |
55 | struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); | 56 | struct tegra_bo *bo = tegra_fb_get_plane(fb, i); |
56 | 57 | ||
57 | window.base[i] = gem->paddr + fb->offsets[i]; | 58 | window.base[i] = bo->paddr + fb->offsets[i]; |
58 | 59 | ||
59 | /* | 60 | /* |
60 | * Tegra doesn't support different strides for U and V planes | 61 | * Tegra doesn't support different strides for U and V planes |
@@ -137,7 +138,7 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc) | |||
137 | static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | 138 | static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, |
138 | struct drm_framebuffer *fb) | 139 | struct drm_framebuffer *fb) |
139 | { | 140 | { |
140 | struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, 0); | 141 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); |
141 | unsigned long value; | 142 | unsigned long value; |
142 | 143 | ||
143 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | 144 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); |
@@ -145,7 +146,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
145 | value = fb->offsets[0] + y * fb->pitches[0] + | 146 | value = fb->offsets[0] + y * fb->pitches[0] + |
146 | x * fb->bits_per_pixel / 8; | 147 | x * fb->bits_per_pixel / 8; |
147 | 148 | ||
148 | tegra_dc_writel(dc, gem->paddr + value, DC_WINBUF_START_ADDR); | 149 | tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR); |
149 | tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); | 150 | tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); |
150 | 151 | ||
151 | value = GENERAL_UPDATE | WIN_A_UPDATE; | 152 | value = GENERAL_UPDATE | WIN_A_UPDATE; |
@@ -187,20 +188,20 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | |||
187 | { | 188 | { |
188 | struct drm_device *drm = dc->base.dev; | 189 | struct drm_device *drm = dc->base.dev; |
189 | struct drm_crtc *crtc = &dc->base; | 190 | struct drm_crtc *crtc = &dc->base; |
190 | struct drm_gem_cma_object *gem; | ||
191 | unsigned long flags, base; | 191 | unsigned long flags, base; |
192 | struct tegra_bo *bo; | ||
192 | 193 | ||
193 | if (!dc->event) | 194 | if (!dc->event) |
194 | return; | 195 | return; |
195 | 196 | ||
196 | gem = drm_fb_cma_get_gem_obj(crtc->fb, 0); | 197 | bo = tegra_fb_get_plane(crtc->fb, 0); |
197 | 198 | ||
198 | /* check if new start address has been latched */ | 199 | /* check if new start address has been latched */ |
199 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); | 200 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); |
200 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); | 201 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); |
201 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); | 202 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); |
202 | 203 | ||
203 | if (base == gem->paddr + crtc->fb->offsets[0]) { | 204 | if (base == bo->paddr + crtc->fb->offsets[0]) { |
204 | spin_lock_irqsave(&drm->event_lock, flags); | 205 | spin_lock_irqsave(&drm->event_lock, flags); |
205 | drm_send_vblank_event(drm, dc->pipe, dc->event); | 206 | drm_send_vblank_event(drm, dc->pipe, dc->event); |
206 | drm_vblank_put(drm, dc->pipe); | 207 | drm_vblank_put(drm, dc->pipe); |
@@ -570,7 +571,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, | |||
570 | struct drm_display_mode *adjusted, | 571 | struct drm_display_mode *adjusted, |
571 | int x, int y, struct drm_framebuffer *old_fb) | 572 | int x, int y, struct drm_framebuffer *old_fb) |
572 | { | 573 | { |
573 | struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(crtc->fb, 0); | 574 | struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0); |
574 | struct tegra_dc *dc = to_tegra_dc(crtc); | 575 | struct tegra_dc *dc = to_tegra_dc(crtc); |
575 | struct tegra_dc_window window; | 576 | struct tegra_dc_window window; |
576 | unsigned long div, value; | 577 | unsigned long div, value; |
@@ -617,7 +618,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, | |||
617 | window.format = tegra_dc_format(crtc->fb->pixel_format); | 618 | window.format = tegra_dc_format(crtc->fb->pixel_format); |
618 | window.bits_per_pixel = crtc->fb->bits_per_pixel; | 619 | window.bits_per_pixel = crtc->fb->bits_per_pixel; |
619 | window.stride[0] = crtc->fb->pitches[0]; | 620 | window.stride[0] = crtc->fb->pitches[0]; |
620 | window.base[0] = gem->paddr; | 621 | window.base[0] = bo->paddr; |
621 | 622 | ||
622 | err = tegra_dc_setup_window(dc, 0, &window); | 623 | err = tegra_dc_setup_window(dc, 0, &window); |
623 | if (err < 0) | 624 | if (err < 0) |
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c index 901f0b47815c..c4e45c16f991 100644 --- a/drivers/gpu/host1x/drm/drm.c +++ b/drivers/gpu/host1x/drm/drm.c | |||
@@ -15,7 +15,10 @@ | |||
15 | #include <asm/dma-iommu.h> | 15 | #include <asm/dma-iommu.h> |
16 | 16 | ||
17 | #include "host1x_client.h" | 17 | #include "host1x_client.h" |
18 | #include "dev.h" | ||
18 | #include "drm.h" | 19 | #include "drm.h" |
20 | #include "gem.h" | ||
21 | #include "syncpt.h" | ||
19 | 22 | ||
20 | #define DRIVER_NAME "tegra" | 23 | #define DRIVER_NAME "tegra" |
21 | #define DRIVER_DESC "NVIDIA Tegra graphics" | 24 | #define DRIVER_DESC "NVIDIA Tegra graphics" |
@@ -281,7 +284,7 @@ static void tegra_drm_lastclose(struct drm_device *drm) | |||
281 | { | 284 | { |
282 | struct host1x_drm *host1x = drm->dev_private; | 285 | struct host1x_drm *host1x = drm->dev_private; |
283 | 286 | ||
284 | drm_fbdev_cma_restore_mode(host1x->fbdev); | 287 | tegra_fbdev_restore_mode(host1x->fbdev); |
285 | } | 288 | } |
286 | 289 | ||
287 | static struct drm_ioctl_desc tegra_drm_ioctls[] = { | 290 | static struct drm_ioctl_desc tegra_drm_ioctls[] = { |
@@ -292,7 +295,7 @@ static const struct file_operations tegra_drm_fops = { | |||
292 | .open = drm_open, | 295 | .open = drm_open, |
293 | .release = drm_release, | 296 | .release = drm_release, |
294 | .unlocked_ioctl = drm_ioctl, | 297 | .unlocked_ioctl = drm_ioctl, |
295 | .mmap = drm_gem_cma_mmap, | 298 | .mmap = tegra_drm_mmap, |
296 | .poll = drm_poll, | 299 | .poll = drm_poll, |
297 | .fasync = drm_fasync, | 300 | .fasync = drm_fasync, |
298 | .read = drm_read, | 301 | .read = drm_read, |
@@ -408,11 +411,11 @@ struct drm_driver tegra_drm_driver = { | |||
408 | .debugfs_cleanup = tegra_debugfs_cleanup, | 411 | .debugfs_cleanup = tegra_debugfs_cleanup, |
409 | #endif | 412 | #endif |
410 | 413 | ||
411 | .gem_free_object = drm_gem_cma_free_object, | 414 | .gem_free_object = tegra_bo_free_object, |
412 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 415 | .gem_vm_ops = &tegra_bo_vm_ops, |
413 | .dumb_create = drm_gem_cma_dumb_create, | 416 | .dumb_create = tegra_bo_dumb_create, |
414 | .dumb_map_offset = drm_gem_cma_dumb_map_offset, | 417 | .dumb_map_offset = tegra_bo_dumb_map_offset, |
415 | .dumb_destroy = drm_gem_cma_dumb_destroy, | 418 | .dumb_destroy = tegra_bo_dumb_destroy, |
416 | 419 | ||
417 | .ioctls = tegra_drm_ioctls, | 420 | .ioctls = tegra_drm_ioctls, |
418 | .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls), | 421 | .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls), |
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h index 0b8738fc444c..3864a39f8ad3 100644 --- a/drivers/gpu/host1x/drm/drm.h +++ b/drivers/gpu/host1x/drm/drm.h | |||
@@ -14,10 +14,19 @@ | |||
14 | #include <drm/drm_crtc_helper.h> | 14 | #include <drm/drm_crtc_helper.h> |
15 | #include <drm/drm_edid.h> | 15 | #include <drm/drm_edid.h> |
16 | #include <drm/drm_fb_helper.h> | 16 | #include <drm/drm_fb_helper.h> |
17 | #include <drm/drm_gem_cma_helper.h> | ||
18 | #include <drm/drm_fb_cma_helper.h> | ||
19 | #include <drm/drm_fixed.h> | 17 | #include <drm/drm_fixed.h> |
20 | 18 | ||
19 | struct tegra_fb { | ||
20 | struct drm_framebuffer base; | ||
21 | struct tegra_bo **planes; | ||
22 | unsigned int num_planes; | ||
23 | }; | ||
24 | |||
25 | struct tegra_fbdev { | ||
26 | struct drm_fb_helper base; | ||
27 | struct tegra_fb *fb; | ||
28 | }; | ||
29 | |||
21 | struct host1x_drm { | 30 | struct host1x_drm { |
22 | struct drm_device *drm; | 31 | struct drm_device *drm; |
23 | struct device *dev; | 32 | struct device *dev; |
@@ -33,7 +42,7 @@ struct host1x_drm { | |||
33 | struct mutex clients_lock; | 42 | struct mutex clients_lock; |
34 | struct list_head clients; | 43 | struct list_head clients; |
35 | 44 | ||
36 | struct drm_fbdev_cma *fbdev; | 45 | struct tegra_fbdev *fbdev; |
37 | }; | 46 | }; |
38 | 47 | ||
39 | struct host1x_client; | 48 | struct host1x_client; |
@@ -226,8 +235,11 @@ extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output | |||
226 | extern int tegra_output_exit(struct tegra_output *output); | 235 | extern int tegra_output_exit(struct tegra_output *output); |
227 | 236 | ||
228 | /* from fb.c */ | 237 | /* from fb.c */ |
238 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, | ||
239 | unsigned int index); | ||
229 | extern int tegra_drm_fb_init(struct drm_device *drm); | 240 | extern int tegra_drm_fb_init(struct drm_device *drm); |
230 | extern void tegra_drm_fb_exit(struct drm_device *drm); | 241 | extern void tegra_drm_fb_exit(struct drm_device *drm); |
242 | extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); | ||
231 | 243 | ||
232 | extern struct drm_driver tegra_drm_driver; | 244 | extern struct drm_driver tegra_drm_driver; |
233 | 245 | ||
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c index 6ed885aead48..979a3e32b78b 100644 --- a/drivers/gpu/host1x/drm/fb.c +++ b/drivers/gpu/host1x/drm/fb.c | |||
@@ -1,30 +1,343 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 Avionic Design GmbH | 2 | * Copyright (C) 2012-2013 Avionic Design GmbH |
3 | * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. | 3 | * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. |
4 | * | 4 | * |
5 | * Based on the KMS/FB CMA helpers | ||
6 | * Copyright (C) 2012 Analog Device Inc. | ||
7 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
8 | */ | 11 | */ |
9 | 12 | ||
13 | #include <linux/module.h> | ||
14 | |||
10 | #include "drm.h" | 15 | #include "drm.h" |
16 | #include "gem.h" | ||
17 | |||
18 | static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb) | ||
19 | { | ||
20 | return container_of(fb, struct tegra_fb, base); | ||
21 | } | ||
22 | |||
23 | static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper) | ||
24 | { | ||
25 | return container_of(helper, struct tegra_fbdev, base); | ||
26 | } | ||
27 | |||
28 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, | ||
29 | unsigned int index) | ||
30 | { | ||
31 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | ||
32 | |||
33 | if (index >= drm_format_num_planes(framebuffer->pixel_format)) | ||
34 | return NULL; | ||
35 | |||
36 | return fb->planes[index]; | ||
37 | } | ||
38 | |||
39 | static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) | ||
40 | { | ||
41 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | ||
42 | unsigned int i; | ||
43 | |||
44 | for (i = 0; i < fb->num_planes; i++) { | ||
45 | struct tegra_bo *bo = fb->planes[i]; | ||
46 | |||
47 | if (bo) | ||
48 | drm_gem_object_unreference_unlocked(&bo->gem); | ||
49 | } | ||
50 | |||
51 | drm_framebuffer_cleanup(framebuffer); | ||
52 | kfree(fb->planes); | ||
53 | kfree(fb); | ||
54 | } | ||
55 | |||
56 | static int tegra_fb_create_handle(struct drm_framebuffer *framebuffer, | ||
57 | struct drm_file *file, unsigned int *handle) | ||
58 | { | ||
59 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | ||
60 | |||
61 | return drm_gem_handle_create(file, &fb->planes[0]->gem, handle); | ||
62 | } | ||
63 | |||
64 | static struct drm_framebuffer_funcs tegra_fb_funcs = { | ||
65 | .destroy = tegra_fb_destroy, | ||
66 | .create_handle = tegra_fb_create_handle, | ||
67 | }; | ||
68 | |||
69 | static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm, | ||
70 | struct drm_mode_fb_cmd2 *mode_cmd, | ||
71 | struct tegra_bo **planes, | ||
72 | unsigned int num_planes) | ||
73 | { | ||
74 | struct tegra_fb *fb; | ||
75 | unsigned int i; | ||
76 | int err; | ||
77 | |||
78 | fb = kzalloc(sizeof(*fb), GFP_KERNEL); | ||
79 | if (!fb) | ||
80 | return ERR_PTR(-ENOMEM); | ||
81 | |||
82 | fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL); | ||
83 | if (!fb->planes) | ||
84 | return ERR_PTR(-ENOMEM); | ||
85 | |||
86 | fb->num_planes = num_planes; | ||
87 | |||
88 | drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); | ||
89 | |||
90 | for (i = 0; i < fb->num_planes; i++) | ||
91 | fb->planes[i] = planes[i]; | ||
92 | |||
93 | err = drm_framebuffer_init(drm, &fb->base, &tegra_fb_funcs); | ||
94 | if (err < 0) { | ||
95 | dev_err(drm->dev, "failed to initialize framebuffer: %d\n", | ||
96 | err); | ||
97 | kfree(fb->planes); | ||
98 | kfree(fb); | ||
99 | return ERR_PTR(err); | ||
100 | } | ||
101 | |||
102 | return fb; | ||
103 | } | ||
104 | |||
105 | static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, | ||
106 | struct drm_file *file, | ||
107 | struct drm_mode_fb_cmd2 *cmd) | ||
108 | { | ||
109 | unsigned int hsub, vsub, i; | ||
110 | struct tegra_bo *planes[4]; | ||
111 | struct drm_gem_object *gem; | ||
112 | struct tegra_fb *fb; | ||
113 | int err; | ||
114 | |||
115 | hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format); | ||
116 | vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format); | ||
117 | |||
118 | for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) { | ||
119 | unsigned int width = cmd->width / (i ? hsub : 1); | ||
120 | unsigned int height = cmd->height / (i ? vsub : 1); | ||
121 | unsigned int size, bpp; | ||
122 | |||
123 | gem = drm_gem_object_lookup(drm, file, cmd->handles[i]); | ||
124 | if (!gem) { | ||
125 | err = -ENXIO; | ||
126 | goto unreference; | ||
127 | } | ||
128 | |||
129 | bpp = drm_format_plane_cpp(cmd->pixel_format, i); | ||
130 | |||
131 | size = (height - 1) * cmd->pitches[i] + | ||
132 | width * bpp + cmd->offsets[i]; | ||
133 | |||
134 | if (gem->size < size) { | ||
135 | err = -EINVAL; | ||
136 | goto unreference; | ||
137 | } | ||
138 | |||
139 | planes[i] = to_tegra_bo(gem); | ||
140 | } | ||
141 | |||
142 | fb = tegra_fb_alloc(drm, cmd, planes, i); | ||
143 | if (IS_ERR(fb)) { | ||
144 | err = PTR_ERR(fb); | ||
145 | goto unreference; | ||
146 | } | ||
147 | |||
148 | return &fb->base; | ||
149 | |||
150 | unreference: | ||
151 | while (i--) | ||
152 | drm_gem_object_unreference_unlocked(&planes[i]->gem); | ||
11 | 153 | ||
12 | static void tegra_drm_fb_output_poll_changed(struct drm_device *drm) | 154 | return ERR_PTR(err); |
155 | } | ||
156 | |||
157 | static struct fb_ops tegra_fb_ops = { | ||
158 | .owner = THIS_MODULE, | ||
159 | .fb_fillrect = sys_fillrect, | ||
160 | .fb_copyarea = sys_copyarea, | ||
161 | .fb_imageblit = sys_imageblit, | ||
162 | .fb_check_var = drm_fb_helper_check_var, | ||
163 | .fb_set_par = drm_fb_helper_set_par, | ||
164 | .fb_blank = drm_fb_helper_blank, | ||
165 | .fb_pan_display = drm_fb_helper_pan_display, | ||
166 | .fb_setcmap = drm_fb_helper_setcmap, | ||
167 | }; | ||
168 | |||
169 | static int tegra_fbdev_probe(struct drm_fb_helper *helper, | ||
170 | struct drm_fb_helper_surface_size *sizes) | ||
171 | { | ||
172 | struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); | ||
173 | struct drm_device *drm = helper->dev; | ||
174 | struct drm_mode_fb_cmd2 cmd = { 0 }; | ||
175 | unsigned int bytes_per_pixel; | ||
176 | struct drm_framebuffer *fb; | ||
177 | unsigned long offset; | ||
178 | struct fb_info *info; | ||
179 | struct tegra_bo *bo; | ||
180 | size_t size; | ||
181 | int err; | ||
182 | |||
183 | bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); | ||
184 | |||
185 | cmd.width = sizes->surface_width; | ||
186 | cmd.height = sizes->surface_height; | ||
187 | cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; | ||
188 | cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, | ||
189 | sizes->surface_depth); | ||
190 | |||
191 | size = cmd.pitches[0] * cmd.height; | ||
192 | |||
193 | bo = tegra_bo_create(drm, size); | ||
194 | if (IS_ERR(bo)) | ||
195 | return PTR_ERR(bo); | ||
196 | |||
197 | info = framebuffer_alloc(0, drm->dev); | ||
198 | if (!info) { | ||
199 | dev_err(drm->dev, "failed to allocate framebuffer info\n"); | ||
200 | tegra_bo_free_object(&bo->gem); | ||
201 | return -ENOMEM; | ||
202 | } | ||
203 | |||
204 | fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1); | ||
205 | if (IS_ERR(fbdev->fb)) { | ||
206 | dev_err(drm->dev, "failed to allocate DRM framebuffer\n"); | ||
207 | err = PTR_ERR(fbdev->fb); | ||
208 | goto release; | ||
209 | } | ||
210 | |||
211 | fb = &fbdev->fb->base; | ||
212 | helper->fb = fb; | ||
213 | helper->fbdev = info; | ||
214 | |||
215 | info->par = helper; | ||
216 | info->flags = FBINFO_FLAG_DEFAULT; | ||
217 | info->fbops = &tegra_fb_ops; | ||
218 | |||
219 | err = fb_alloc_cmap(&info->cmap, 256, 0); | ||
220 | if (err < 0) { | ||
221 | dev_err(drm->dev, "failed to allocate color map: %d\n", err); | ||
222 | goto destroy; | ||
223 | } | ||
224 | |||
225 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); | ||
226 | drm_fb_helper_fill_var(info, helper, fb->width, fb->height); | ||
227 | |||
228 | offset = info->var.xoffset * bytes_per_pixel + | ||
229 | info->var.yoffset * fb->pitches[0]; | ||
230 | |||
231 | drm->mode_config.fb_base = (resource_size_t)bo->paddr; | ||
232 | info->screen_base = bo->vaddr + offset; | ||
233 | info->screen_size = size; | ||
234 | info->fix.smem_start = (unsigned long)(bo->paddr + offset); | ||
235 | info->fix.smem_len = size; | ||
236 | |||
237 | return 0; | ||
238 | |||
239 | destroy: | ||
240 | drm_framebuffer_unregister_private(fb); | ||
241 | tegra_fb_destroy(fb); | ||
242 | release: | ||
243 | framebuffer_release(info); | ||
244 | return err; | ||
245 | } | ||
246 | |||
247 | static struct drm_fb_helper_funcs tegra_fb_helper_funcs = { | ||
248 | .fb_probe = tegra_fbdev_probe, | ||
249 | }; | ||
250 | |||
251 | static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm, | ||
252 | unsigned int preferred_bpp, | ||
253 | unsigned int num_crtc, | ||
254 | unsigned int max_connectors) | ||
255 | { | ||
256 | struct drm_fb_helper *helper; | ||
257 | struct tegra_fbdev *fbdev; | ||
258 | int err; | ||
259 | |||
260 | fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); | ||
261 | if (!fbdev) { | ||
262 | dev_err(drm->dev, "failed to allocate DRM fbdev\n"); | ||
263 | return ERR_PTR(-ENOMEM); | ||
264 | } | ||
265 | |||
266 | fbdev->base.funcs = &tegra_fb_helper_funcs; | ||
267 | helper = &fbdev->base; | ||
268 | |||
269 | err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors); | ||
270 | if (err < 0) { | ||
271 | dev_err(drm->dev, "failed to initialize DRM FB helper\n"); | ||
272 | goto free; | ||
273 | } | ||
274 | |||
275 | err = drm_fb_helper_single_add_all_connectors(&fbdev->base); | ||
276 | if (err < 0) { | ||
277 | dev_err(drm->dev, "failed to add connectors\n"); | ||
278 | goto fini; | ||
279 | } | ||
280 | |||
281 | drm_helper_disable_unused_functions(drm); | ||
282 | |||
283 | err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp); | ||
284 | if (err < 0) { | ||
285 | dev_err(drm->dev, "failed to set initial configuration\n"); | ||
286 | goto fini; | ||
287 | } | ||
288 | |||
289 | return fbdev; | ||
290 | |||
291 | fini: | ||
292 | drm_fb_helper_fini(&fbdev->base); | ||
293 | free: | ||
294 | kfree(fbdev); | ||
295 | return ERR_PTR(err); | ||
296 | } | ||
297 | |||
298 | static void tegra_fbdev_free(struct tegra_fbdev *fbdev) | ||
299 | { | ||
300 | struct fb_info *info = fbdev->base.fbdev; | ||
301 | |||
302 | if (info) { | ||
303 | int err; | ||
304 | |||
305 | err = unregister_framebuffer(info); | ||
306 | if (err < 0) | ||
307 | DRM_DEBUG_KMS("failed to unregister framebuffer\n"); | ||
308 | |||
309 | if (info->cmap.len) | ||
310 | fb_dealloc_cmap(&info->cmap); | ||
311 | |||
312 | framebuffer_release(info); | ||
313 | } | ||
314 | |||
315 | if (fbdev->fb) { | ||
316 | drm_framebuffer_unregister_private(&fbdev->fb->base); | ||
317 | tegra_fb_destroy(&fbdev->fb->base); | ||
318 | } | ||
319 | |||
320 | drm_fb_helper_fini(&fbdev->base); | ||
321 | kfree(fbdev); | ||
322 | } | ||
323 | |||
324 | static void tegra_fb_output_poll_changed(struct drm_device *drm) | ||
13 | { | 325 | { |
14 | struct host1x_drm *host1x = drm->dev_private; | 326 | struct host1x_drm *host1x = drm->dev_private; |
15 | 327 | ||
16 | drm_fbdev_cma_hotplug_event(host1x->fbdev); | 328 | if (host1x->fbdev) |
329 | drm_fb_helper_hotplug_event(&host1x->fbdev->base); | ||
17 | } | 330 | } |
18 | 331 | ||
19 | static const struct drm_mode_config_funcs tegra_drm_mode_funcs = { | 332 | static const struct drm_mode_config_funcs tegra_drm_mode_funcs = { |
20 | .fb_create = drm_fb_cma_create, | 333 | .fb_create = tegra_fb_create, |
21 | .output_poll_changed = tegra_drm_fb_output_poll_changed, | 334 | .output_poll_changed = tegra_fb_output_poll_changed, |
22 | }; | 335 | }; |
23 | 336 | ||
24 | int tegra_drm_fb_init(struct drm_device *drm) | 337 | int tegra_drm_fb_init(struct drm_device *drm) |
25 | { | 338 | { |
26 | struct host1x_drm *host1x = drm->dev_private; | 339 | struct host1x_drm *host1x = drm->dev_private; |
27 | struct drm_fbdev_cma *fbdev; | 340 | struct tegra_fbdev *fbdev; |
28 | 341 | ||
29 | drm->mode_config.min_width = 0; | 342 | drm->mode_config.min_width = 0; |
30 | drm->mode_config.min_height = 0; | 343 | drm->mode_config.min_height = 0; |
@@ -34,7 +347,7 @@ int tegra_drm_fb_init(struct drm_device *drm) | |||
34 | 347 | ||
35 | drm->mode_config.funcs = &tegra_drm_mode_funcs; | 348 | drm->mode_config.funcs = &tegra_drm_mode_funcs; |
36 | 349 | ||
37 | fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, | 350 | fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc, |
38 | drm->mode_config.num_connector); | 351 | drm->mode_config.num_connector); |
39 | if (IS_ERR(fbdev)) | 352 | if (IS_ERR(fbdev)) |
40 | return PTR_ERR(fbdev); | 353 | return PTR_ERR(fbdev); |
@@ -48,5 +361,14 @@ void tegra_drm_fb_exit(struct drm_device *drm) | |||
48 | { | 361 | { |
49 | struct host1x_drm *host1x = drm->dev_private; | 362 | struct host1x_drm *host1x = drm->dev_private; |
50 | 363 | ||
51 | drm_fbdev_cma_fini(host1x->fbdev); | 364 | tegra_fbdev_free(host1x->fbdev); |
365 | } | ||
366 | |||
367 | void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev) | ||
368 | { | ||
369 | if (fbdev) { | ||
370 | drm_modeset_lock_all(fbdev->base.dev); | ||
371 | drm_fb_helper_restore_fbdev_mode(&fbdev->base); | ||
372 | drm_modeset_unlock_all(fbdev->base.dev); | ||
373 | } | ||
52 | } | 374 | } |
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c new file mode 100644 index 000000000000..c5e9a9b494c2 --- /dev/null +++ b/drivers/gpu/host1x/drm/gem.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* | ||
2 | * NVIDIA Tegra DRM GEM helper functions | ||
3 | * | ||
4 | * Copyright (C) 2012 Sascha Hauer, Pengutronix | ||
5 | * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved. | ||
6 | * | ||
7 | * Based on the GEM/CMA helpers | ||
8 | * | ||
9 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version 2 | ||
14 | * of the License, or (at your option) any later version. | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/mm.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/export.h> | ||
25 | #include <linux/dma-mapping.h> | ||
26 | |||
27 | #include <drm/drmP.h> | ||
28 | #include <drm/drm.h> | ||
29 | |||
30 | #include "gem.h" | ||
31 | |||
32 | static inline struct tegra_bo *host1x_to_drm_bo(struct host1x_bo *bo) | ||
33 | { | ||
34 | return container_of(bo, struct tegra_bo, base); | ||
35 | } | ||
36 | |||
37 | static void tegra_bo_put(struct host1x_bo *bo) | ||
38 | { | ||
39 | struct tegra_bo *obj = host1x_to_drm_bo(bo); | ||
40 | struct drm_device *drm = obj->gem.dev; | ||
41 | |||
42 | mutex_lock(&drm->struct_mutex); | ||
43 | drm_gem_object_unreference(&obj->gem); | ||
44 | mutex_unlock(&drm->struct_mutex); | ||
45 | } | ||
46 | |||
47 | static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt) | ||
48 | { | ||
49 | struct tegra_bo *obj = host1x_to_drm_bo(bo); | ||
50 | |||
51 | return obj->paddr; | ||
52 | } | ||
53 | |||
54 | static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | static void *tegra_bo_mmap(struct host1x_bo *bo) | ||
59 | { | ||
60 | struct tegra_bo *obj = host1x_to_drm_bo(bo); | ||
61 | |||
62 | return obj->vaddr; | ||
63 | } | ||
64 | |||
65 | static void tegra_bo_munmap(struct host1x_bo *bo, void *addr) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page) | ||
70 | { | ||
71 | struct tegra_bo *obj = host1x_to_drm_bo(bo); | ||
72 | |||
73 | return obj->vaddr + page * PAGE_SIZE; | ||
74 | } | ||
75 | |||
76 | static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page, | ||
77 | void *addr) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo) | ||
82 | { | ||
83 | struct tegra_bo *obj = host1x_to_drm_bo(bo); | ||
84 | struct drm_device *drm = obj->gem.dev; | ||
85 | |||
86 | mutex_lock(&drm->struct_mutex); | ||
87 | drm_gem_object_reference(&obj->gem); | ||
88 | mutex_unlock(&drm->struct_mutex); | ||
89 | |||
90 | return bo; | ||
91 | } | ||
92 | |||
93 | const struct host1x_bo_ops tegra_bo_ops = { | ||
94 | .get = tegra_bo_get, | ||
95 | .put = tegra_bo_put, | ||
96 | .pin = tegra_bo_pin, | ||
97 | .unpin = tegra_bo_unpin, | ||
98 | .mmap = tegra_bo_mmap, | ||
99 | .munmap = tegra_bo_munmap, | ||
100 | .kmap = tegra_bo_kmap, | ||
101 | .kunmap = tegra_bo_kunmap, | ||
102 | }; | ||
103 | |||
104 | static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo) | ||
105 | { | ||
106 | dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr); | ||
107 | } | ||
108 | |||
109 | unsigned int tegra_bo_get_mmap_offset(struct tegra_bo *bo) | ||
110 | { | ||
111 | return (unsigned int)bo->gem.map_list.hash.key << PAGE_SHIFT; | ||
112 | } | ||
113 | |||
114 | struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size) | ||
115 | { | ||
116 | struct tegra_bo *bo; | ||
117 | int err; | ||
118 | |||
119 | bo = kzalloc(sizeof(*bo), GFP_KERNEL); | ||
120 | if (!bo) | ||
121 | return ERR_PTR(-ENOMEM); | ||
122 | |||
123 | host1x_bo_init(&bo->base, &tegra_bo_ops); | ||
124 | size = round_up(size, PAGE_SIZE); | ||
125 | |||
126 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, | ||
127 | GFP_KERNEL | __GFP_NOWARN); | ||
128 | if (!bo->vaddr) { | ||
129 | dev_err(drm->dev, "failed to allocate buffer with size %u\n", | ||
130 | size); | ||
131 | err = -ENOMEM; | ||
132 | goto err_dma; | ||
133 | } | ||
134 | |||
135 | err = drm_gem_object_init(drm, &bo->gem, size); | ||
136 | if (err) | ||
137 | goto err_init; | ||
138 | |||
139 | err = drm_gem_create_mmap_offset(&bo->gem); | ||
140 | if (err) | ||
141 | goto err_mmap; | ||
142 | |||
143 | return bo; | ||
144 | |||
145 | err_mmap: | ||
146 | drm_gem_object_release(&bo->gem); | ||
147 | err_init: | ||
148 | tegra_bo_destroy(drm, bo); | ||
149 | err_dma: | ||
150 | kfree(bo); | ||
151 | |||
152 | return ERR_PTR(err); | ||
153 | |||
154 | } | ||
155 | |||
156 | struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, | ||
157 | struct drm_device *drm, | ||
158 | unsigned int size, | ||
159 | unsigned int *handle) | ||
160 | { | ||
161 | struct tegra_bo *bo; | ||
162 | int ret; | ||
163 | |||
164 | bo = tegra_bo_create(drm, size); | ||
165 | if (IS_ERR(bo)) | ||
166 | return bo; | ||
167 | |||
168 | ret = drm_gem_handle_create(file, &bo->gem, handle); | ||
169 | if (ret) | ||
170 | goto err; | ||
171 | |||
172 | drm_gem_object_unreference_unlocked(&bo->gem); | ||
173 | |||
174 | return bo; | ||
175 | |||
176 | err: | ||
177 | tegra_bo_free_object(&bo->gem); | ||
178 | return ERR_PTR(ret); | ||
179 | } | ||
180 | |||
181 | void tegra_bo_free_object(struct drm_gem_object *gem) | ||
182 | { | ||
183 | struct tegra_bo *bo = to_tegra_bo(gem); | ||
184 | |||
185 | if (gem->map_list.map) | ||
186 | drm_gem_free_mmap_offset(gem); | ||
187 | |||
188 | drm_gem_object_release(gem); | ||
189 | tegra_bo_destroy(gem->dev, bo); | ||
190 | |||
191 | kfree(bo); | ||
192 | } | ||
193 | |||
194 | int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, | ||
195 | struct drm_mode_create_dumb *args) | ||
196 | { | ||
197 | int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); | ||
198 | struct tegra_bo *bo; | ||
199 | |||
200 | if (args->pitch < min_pitch) | ||
201 | args->pitch = min_pitch; | ||
202 | |||
203 | if (args->size < args->pitch * args->height) | ||
204 | args->size = args->pitch * args->height; | ||
205 | |||
206 | bo = tegra_bo_create_with_handle(file, drm, args->size, | ||
207 | &args->handle); | ||
208 | if (IS_ERR(bo)) | ||
209 | return PTR_ERR(bo); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, | ||
215 | uint32_t handle, uint64_t *offset) | ||
216 | { | ||
217 | struct drm_gem_object *gem; | ||
218 | struct tegra_bo *bo; | ||
219 | |||
220 | mutex_lock(&drm->struct_mutex); | ||
221 | |||
222 | gem = drm_gem_object_lookup(drm, file, handle); | ||
223 | if (!gem) { | ||
224 | dev_err(drm->dev, "failed to lookup GEM object\n"); | ||
225 | mutex_unlock(&drm->struct_mutex); | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | bo = to_tegra_bo(gem); | ||
230 | |||
231 | *offset = tegra_bo_get_mmap_offset(bo); | ||
232 | |||
233 | drm_gem_object_unreference(gem); | ||
234 | |||
235 | mutex_unlock(&drm->struct_mutex); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | const struct vm_operations_struct tegra_bo_vm_ops = { | ||
241 | .open = drm_gem_vm_open, | ||
242 | .close = drm_gem_vm_close, | ||
243 | }; | ||
244 | |||
245 | int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) | ||
246 | { | ||
247 | struct drm_gem_object *gem; | ||
248 | struct tegra_bo *bo; | ||
249 | int ret; | ||
250 | |||
251 | ret = drm_gem_mmap(file, vma); | ||
252 | if (ret) | ||
253 | return ret; | ||
254 | |||
255 | gem = vma->vm_private_data; | ||
256 | bo = to_tegra_bo(gem); | ||
257 | |||
258 | ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT, | ||
259 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
260 | if (ret) | ||
261 | drm_gem_vm_close(vma); | ||
262 | |||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | int tegra_bo_dumb_destroy(struct drm_file *file, struct drm_device *drm, | ||
267 | unsigned int handle) | ||
268 | { | ||
269 | return drm_gem_handle_delete(file, handle); | ||
270 | } | ||
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h new file mode 100644 index 000000000000..34de2b486eb7 --- /dev/null +++ b/drivers/gpu/host1x/drm/gem.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Tegra host1x GEM implementation | ||
3 | * | ||
4 | * Copyright (c) 2012-2013, NVIDIA Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef __HOST1X_GEM_H | ||
20 | #define __HOST1X_GEM_H | ||
21 | |||
22 | #include <drm/drm.h> | ||
23 | #include <drm/drmP.h> | ||
24 | |||
25 | #include "host1x_bo.h" | ||
26 | |||
27 | struct tegra_bo { | ||
28 | struct drm_gem_object gem; | ||
29 | struct host1x_bo base; | ||
30 | dma_addr_t paddr; | ||
31 | void *vaddr; | ||
32 | }; | ||
33 | |||
34 | static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) | ||
35 | { | ||
36 | return container_of(gem, struct tegra_bo, gem); | ||
37 | } | ||
38 | |||
39 | extern const struct host1x_bo_ops tegra_bo_ops; | ||
40 | |||
41 | struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size); | ||
42 | struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, | ||
43 | struct drm_device *drm, | ||
44 | unsigned int size, | ||
45 | unsigned int *handle); | ||
46 | void tegra_bo_free_object(struct drm_gem_object *gem); | ||
47 | unsigned int tegra_bo_get_mmap_offset(struct tegra_bo *bo); | ||
48 | int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, | ||
49 | struct drm_mode_create_dumb *args); | ||
50 | int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, | ||
51 | uint32_t handle, uint64_t *offset); | ||
52 | int tegra_bo_dumb_destroy(struct drm_file *file, struct drm_device *drm, | ||
53 | unsigned int handle); | ||
54 | |||
55 | int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma); | ||
56 | |||
57 | extern const struct vm_operations_struct tegra_bo_vm_ops; | ||
58 | |||
59 | #endif | ||