diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2013-10-07 03:47:58 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2013-10-31 04:55:46 -0400 |
commit | db7fbdfd25ee009165b6c3b80a9d1c6d8534ad94 (patch) | |
tree | 1ba0c25b63b227a7f139b03ae217daf0b7ec1f81 | |
parent | 773af77fc479fd454c3f6836f86bf63996545cf4 (diff) |
drm/tegra: Support bottom-up buffer objects
The gr3d engine renders images bottom-up. Allow buffers that are used
for 3D content to be marked as such and implement support in the display
controller to present them 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 | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.h | 3 | ||||
-rw-r--r-- | include/uapi/drm/tegra_drm.h | 3 |
7 files changed, 44 insertions, 2 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index c51aaf7555f5..ae1cb31ead7e 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.bottom_up = tegra_fb_is_bottom_up(fb); | ||
50 | window.tiled = tegra_fb_is_tiled(fb); | 51 | window.tiled = tegra_fb_is_tiled(fb); |
51 | 52 | ||
52 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { | 53 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { |
@@ -147,6 +148,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
147 | { | 148 | { |
148 | unsigned int format = tegra_dc_format(fb->pixel_format); | 149 | unsigned int format = tegra_dc_format(fb->pixel_format); |
149 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); | 150 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); |
151 | unsigned int h_offset = 0, v_offset = 0; | ||
150 | unsigned long value; | 152 | unsigned long value; |
151 | 153 | ||
152 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | 154 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); |
@@ -168,6 +170,22 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
168 | 170 | ||
169 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); | 171 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); |
170 | 172 | ||
173 | /* make sure bottom-up buffers are properly displayed */ | ||
174 | if (tegra_fb_is_bottom_up(fb)) { | ||
175 | value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); | ||
176 | value |= INVERT_V; | ||
177 | tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); | ||
178 | |||
179 | v_offset += fb->height - 1; | ||
180 | } else { | ||
181 | value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); | ||
182 | value &= ~INVERT_V; | ||
183 | tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); | ||
184 | } | ||
185 | |||
186 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); | ||
187 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); | ||
188 | |||
171 | value = GENERAL_UPDATE | WIN_A_UPDATE; | 189 | value = GENERAL_UPDATE | WIN_A_UPDATE; |
172 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); | 190 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); |
173 | 191 | ||
@@ -517,6 +535,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
517 | tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE); | 535 | tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE); |
518 | } | 536 | } |
519 | 537 | ||
538 | if (window->bottom_up) | ||
539 | v_offset += window->src.h - 1; | ||
540 | |||
520 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); | 541 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); |
521 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); | 542 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); |
522 | 543 | ||
@@ -548,6 +569,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
548 | value |= COLOR_EXPAND; | 569 | value |= COLOR_EXPAND; |
549 | } | 570 | } |
550 | 571 | ||
572 | if (window->bottom_up) | ||
573 | value |= INVERT_V; | ||
574 | |||
551 | tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); | 575 | tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); |
552 | 576 | ||
553 | /* | 577 | /* |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index e0b94c26bb86..91bbda291470 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
@@ -302,6 +302,7 @@ | |||
302 | #define DC_WIN_CSC_KVB 0x618 | 302 | #define DC_WIN_CSC_KVB 0x618 |
303 | 303 | ||
304 | #define DC_WIN_WIN_OPTIONS 0x700 | 304 | #define DC_WIN_WIN_OPTIONS 0x700 |
305 | #define INVERT_V (1 << 2) | ||
305 | #define COLOR_EXPAND (1 << 6) | 306 | #define COLOR_EXPAND (1 << 6) |
306 | #define CSC_ENABLE (1 << 18) | 307 | #define CSC_ENABLE (1 << 18) |
307 | #define WIN_ENABLE (1 << 30) | 308 | #define WIN_ENABLE (1 << 30) |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index e07a10eedae6..fdfe259ed7f8 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 bottom_up; | ||
151 | bool tiled; | 152 | bool tiled; |
152 | }; | 153 | }; |
153 | 154 | ||
@@ -255,6 +256,7 @@ extern int tegra_output_exit(struct tegra_output *output); | |||
255 | /* from fb.c */ | 256 | /* from fb.c */ |
256 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, | 257 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, |
257 | unsigned int index); | 258 | unsigned int index); |
259 | bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); | ||
258 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); | 260 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); |
259 | extern int tegra_drm_fb_init(struct drm_device *drm); | 261 | extern int tegra_drm_fb_init(struct drm_device *drm); |
260 | extern void tegra_drm_fb_exit(struct drm_device *drm); | 262 | extern void tegra_drm_fb_exit(struct drm_device *drm); |
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index fdb00e040046..490f7719e317 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_bottom_up(struct drm_framebuffer *framebuffer) | ||
38 | { | ||
39 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | ||
40 | |||
41 | if (fb->planes[0]->flags & TEGRA_BO_BOTTOM_UP) | ||
42 | return true; | ||
43 | |||
44 | return false; | ||
45 | } | ||
46 | |||
37 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) | 47 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) |
38 | { | 48 | { |
39 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | 49 | struct tegra_fb *fb = to_tegra_fb(framebuffer); |
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index d851ec106cf4..28a9cbc07ab9 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
@@ -132,6 +132,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, | |||
132 | if (flags & DRM_TEGRA_GEM_CREATE_TILED) | 132 | if (flags & DRM_TEGRA_GEM_CREATE_TILED) |
133 | bo->flags |= TEGRA_BO_TILED; | 133 | bo->flags |= TEGRA_BO_TILED; |
134 | 134 | ||
135 | if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP) | ||
136 | bo->flags |= TEGRA_BO_BOTTOM_UP; | ||
137 | |||
135 | return bo; | 138 | return bo; |
136 | 139 | ||
137 | err_mmap: | 140 | err_mmap: |
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index c4993fc2c3bd..7674000bf47d 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h | |||
@@ -24,7 +24,8 @@ | |||
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) | 27 | #define TEGRA_BO_TILED (1 << 0) |
28 | #define TEGRA_BO_BOTTOM_UP (1 << 1) | ||
28 | 29 | ||
29 | struct tegra_bo { | 30 | struct tegra_bo { |
30 | struct drm_gem_object gem; | 31 | struct drm_gem_object gem; |
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index 6b420029a645..0f8575f58db8 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h | |||
@@ -19,7 +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) | 22 | #define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) |
23 | #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) | ||
23 | 24 | ||
24 | struct drm_tegra_gem_create { | 25 | struct drm_tegra_gem_create { |
25 | __u64 size; | 26 | __u64 size; |