diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2013-10-04 16:34:01 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2013-10-31 04:55:46 -0400 |
commit | 773af77fc479fd454c3f6836f86bf63996545cf4 (patch) | |
tree | a3610dd713a97cf934810079da61b1196e85d95b | |
parent | 5f60ed0d840d53e9d65aa54e1a5365af8ce2769e (diff) |
drm/tegra: Add support for tiled buffer objects
The gr2d and gr3d engines work more efficiently on buffers with a tiled
memory layout. Allow created buffers to be marked as tiled so that the
display controller can scan them out properly.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.h | 13 | ||||
-rw-r--r-- | include/uapi/drm/tegra_drm.h | 2 |
8 files changed, 60 insertions, 9 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 054ca1b6bd31..c51aaf7555f5 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -47,6 +47,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
47 | window.dst.h = crtc_h; | 47 | window.dst.h = crtc_h; |
48 | window.format = tegra_dc_format(fb->pixel_format); | 48 | window.format = tegra_dc_format(fb->pixel_format); |
49 | window.bits_per_pixel = fb->bits_per_pixel; | 49 | window.bits_per_pixel = fb->bits_per_pixel; |
50 | window.tiled = tegra_fb_is_tiled(fb); | ||
50 | 51 | ||
51 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { | 52 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { |
52 | struct tegra_bo *bo = tegra_fb_get_plane(fb, i); | 53 | struct tegra_bo *bo = tegra_fb_get_plane(fb, i); |
@@ -157,6 +158,16 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
157 | tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); | 158 | tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); |
158 | tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); | 159 | tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); |
159 | 160 | ||
161 | if (tegra_fb_is_tiled(fb)) { | ||
162 | value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | | ||
163 | DC_WIN_BUFFER_ADDR_MODE_TILE; | ||
164 | } else { | ||
165 | value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | | ||
166 | DC_WIN_BUFFER_ADDR_MODE_LINEAR; | ||
167 | } | ||
168 | |||
169 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); | ||
170 | |||
160 | value = GENERAL_UPDATE | WIN_A_UPDATE; | 171 | value = GENERAL_UPDATE | WIN_A_UPDATE; |
161 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); | 172 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); |
162 | 173 | ||
@@ -509,6 +520,16 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
509 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); | 520 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); |
510 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); | 521 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); |
511 | 522 | ||
523 | if (window->tiled) { | ||
524 | value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | | ||
525 | DC_WIN_BUFFER_ADDR_MODE_TILE; | ||
526 | } else { | ||
527 | value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | | ||
528 | DC_WIN_BUFFER_ADDR_MODE_LINEAR; | ||
529 | } | ||
530 | |||
531 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); | ||
532 | |||
512 | value = WIN_ENABLE; | 533 | value = WIN_ENABLE; |
513 | 534 | ||
514 | if (yuv) { | 535 | if (yuv) { |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 79eaec9aac77..e0b94c26bb86 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
@@ -365,6 +365,10 @@ | |||
365 | #define DC_WIN_BUF_STRIDE 0x70b | 365 | #define DC_WIN_BUF_STRIDE 0x70b |
366 | #define DC_WIN_UV_BUF_STRIDE 0x70c | 366 | #define DC_WIN_UV_BUF_STRIDE 0x70c |
367 | #define DC_WIN_BUFFER_ADDR_MODE 0x70d | 367 | #define DC_WIN_BUFFER_ADDR_MODE 0x70d |
368 | #define DC_WIN_BUFFER_ADDR_MODE_LINEAR (0 << 0) | ||
369 | #define DC_WIN_BUFFER_ADDR_MODE_TILE (1 << 0) | ||
370 | #define DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV (0 << 16) | ||
371 | #define DC_WIN_BUFFER_ADDR_MODE_TILE_UV (1 << 16) | ||
368 | #define DC_WIN_DV_CONTROL 0x70e | 372 | #define DC_WIN_DV_CONTROL 0x70e |
369 | 373 | ||
370 | #define DC_WIN_BLEND_NOKEY 0x70f | 374 | #define DC_WIN_BLEND_NOKEY 0x70f |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 26a2903879d8..ecb6ec735ef1 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -262,7 +262,7 @@ static int tegra_gem_create(struct drm_device *drm, void *data, | |||
262 | struct drm_tegra_gem_create *args = data; | 262 | struct drm_tegra_gem_create *args = data; |
263 | struct tegra_bo *bo; | 263 | struct tegra_bo *bo; |
264 | 264 | ||
265 | bo = tegra_bo_create_with_handle(file, drm, args->size, | 265 | bo = tegra_bo_create_with_handle(file, drm, args->size, args->flags, |
266 | &args->handle); | 266 | &args->handle); |
267 | if (IS_ERR(bo)) | 267 | if (IS_ERR(bo)) |
268 | return PTR_ERR(bo); | 268 | return PTR_ERR(bo); |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index b599fd4650ad..e07a10eedae6 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
@@ -148,6 +148,7 @@ struct tegra_dc_window { | |||
148 | unsigned int format; | 148 | unsigned int format; |
149 | unsigned int stride[2]; | 149 | unsigned int stride[2]; |
150 | unsigned long base[3]; | 150 | unsigned long base[3]; |
151 | bool tiled; | ||
151 | }; | 152 | }; |
152 | 153 | ||
153 | /* from dc.c */ | 154 | /* from dc.c */ |
@@ -254,6 +255,7 @@ extern int tegra_output_exit(struct tegra_output *output); | |||
254 | /* from fb.c */ | 255 | /* from fb.c */ |
255 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, | 256 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, |
256 | unsigned int index); | 257 | unsigned int index); |
258 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); | ||
257 | extern int tegra_drm_fb_init(struct drm_device *drm); | 259 | extern int tegra_drm_fb_init(struct drm_device *drm); |
258 | extern void tegra_drm_fb_exit(struct drm_device *drm); | 260 | extern void tegra_drm_fb_exit(struct drm_device *drm); |
259 | extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); | 261 | extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); |
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 1fd4e196b934..fdb00e040046 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c | |||
@@ -34,6 +34,16 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, | |||
34 | return fb->planes[index]; | 34 | return fb->planes[index]; |
35 | } | 35 | } |
36 | 36 | ||
37 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) | ||
38 | { | ||
39 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | ||
40 | |||
41 | if (fb->planes[0]->flags & TEGRA_BO_TILED) | ||
42 | return true; | ||
43 | |||
44 | return false; | ||
45 | } | ||
46 | |||
37 | static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) | 47 | static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) |
38 | { | 48 | { |
39 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | 49 | struct tegra_fb *fb = to_tegra_fb(framebuffer); |
@@ -188,7 +198,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, | |||
188 | 198 | ||
189 | size = cmd.pitches[0] * cmd.height; | 199 | size = cmd.pitches[0] * cmd.height; |
190 | 200 | ||
191 | bo = tegra_bo_create(drm, size); | 201 | bo = tegra_bo_create(drm, size, 0); |
192 | if (IS_ERR(bo)) | 202 | if (IS_ERR(bo)) |
193 | return PTR_ERR(bo); | 203 | return PTR_ERR(bo); |
194 | 204 | ||
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 267c0c21e5cc..d851ec106cf4 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
@@ -18,6 +18,8 @@ | |||
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <drm/tegra_drm.h> | ||
22 | |||
21 | #include "gem.h" | 23 | #include "gem.h" |
22 | 24 | ||
23 | static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) | 25 | static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) |
@@ -97,7 +99,8 @@ static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo) | |||
97 | dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr); | 99 | dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr); |
98 | } | 100 | } |
99 | 101 | ||
100 | struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size) | 102 | struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, |
103 | unsigned long flags) | ||
101 | { | 104 | { |
102 | struct tegra_bo *bo; | 105 | struct tegra_bo *bo; |
103 | int err; | 106 | int err; |
@@ -126,6 +129,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size) | |||
126 | if (err) | 129 | if (err) |
127 | goto err_mmap; | 130 | goto err_mmap; |
128 | 131 | ||
132 | if (flags & DRM_TEGRA_GEM_CREATE_TILED) | ||
133 | bo->flags |= TEGRA_BO_TILED; | ||
134 | |||
129 | return bo; | 135 | return bo; |
130 | 136 | ||
131 | err_mmap: | 137 | err_mmap: |
@@ -142,12 +148,13 @@ err_dma: | |||
142 | struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, | 148 | struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, |
143 | struct drm_device *drm, | 149 | struct drm_device *drm, |
144 | unsigned int size, | 150 | unsigned int size, |
151 | unsigned long flags, | ||
145 | unsigned int *handle) | 152 | unsigned int *handle) |
146 | { | 153 | { |
147 | struct tegra_bo *bo; | 154 | struct tegra_bo *bo; |
148 | int ret; | 155 | int ret; |
149 | 156 | ||
150 | bo = tegra_bo_create(drm, size); | 157 | bo = tegra_bo_create(drm, size, flags); |
151 | if (IS_ERR(bo)) | 158 | if (IS_ERR(bo)) |
152 | return bo; | 159 | return bo; |
153 | 160 | ||
@@ -187,7 +194,7 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, | |||
187 | if (args->size < args->pitch * args->height) | 194 | if (args->size < args->pitch * args->height) |
188 | args->size = args->pitch * args->height; | 195 | args->size = args->pitch * args->height; |
189 | 196 | ||
190 | bo = tegra_bo_create_with_handle(file, drm, args->size, | 197 | bo = tegra_bo_create_with_handle(file, drm, args->size, 0, |
191 | &args->handle); | 198 | &args->handle); |
192 | if (IS_ERR(bo)) | 199 | if (IS_ERR(bo)) |
193 | return PTR_ERR(bo); | 200 | return PTR_ERR(bo); |
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 2b54f1425d5e..c4993fc2c3bd 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h | |||
@@ -24,9 +24,12 @@ | |||
24 | #include <drm/drm.h> | 24 | #include <drm/drm.h> |
25 | #include <drm/drmP.h> | 25 | #include <drm/drmP.h> |
26 | 26 | ||
27 | #define TEGRA_BO_TILED (1 << 0) | ||
28 | |||
27 | struct tegra_bo { | 29 | struct tegra_bo { |
28 | struct drm_gem_object gem; | 30 | struct drm_gem_object gem; |
29 | struct host1x_bo base; | 31 | struct host1x_bo base; |
32 | unsigned long flags; | ||
30 | dma_addr_t paddr; | 33 | dma_addr_t paddr; |
31 | void *vaddr; | 34 | void *vaddr; |
32 | }; | 35 | }; |
@@ -38,11 +41,13 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) | |||
38 | 41 | ||
39 | extern const struct host1x_bo_ops tegra_bo_ops; | 42 | extern const struct host1x_bo_ops tegra_bo_ops; |
40 | 43 | ||
41 | struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size); | 44 | struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, |
45 | unsigned long flags); | ||
42 | struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, | 46 | struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, |
43 | struct drm_device *drm, | 47 | struct drm_device *drm, |
44 | unsigned int size, | 48 | unsigned int size, |
45 | unsigned int *handle); | 49 | unsigned long flags, |
50 | unsigned int *handle); | ||
46 | void tegra_bo_free_object(struct drm_gem_object *gem); | 51 | void tegra_bo_free_object(struct drm_gem_object *gem); |
47 | int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, | 52 | int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, |
48 | struct drm_mode_create_dumb *args); | 53 | struct drm_mode_create_dumb *args); |
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index 73bde4eaf16c..6b420029a645 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #include <drm/drm.h> | 20 | #include <drm/drm.h> |
21 | 21 | ||
22 | #define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) | ||
23 | |||
22 | struct drm_tegra_gem_create { | 24 | struct drm_tegra_gem_create { |
23 | __u64 size; | 25 | __u64 size; |
24 | __u32 flags; | 26 | __u32 flags; |