summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2013-10-04 22:34:01 +0200
committerThierry Reding <treding@nvidia.com>2013-10-31 09:55:46 +0100
commit773af77fc479fd454c3f6836f86bf63996545cf4 (patch)
treea3610dd713a97cf934810079da61b1196e85d95b
parent5f60ed0d840d53e9d65aa54e1a5365af8ce2769e (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.c21
-rw-r--r--drivers/gpu/drm/tegra/dc.h4
-rw-r--r--drivers/gpu/drm/tegra/drm.c2
-rw-r--r--drivers/gpu/drm/tegra/drm.h2
-rw-r--r--drivers/gpu/drm/tegra/fb.c12
-rw-r--r--drivers/gpu/drm/tegra/gem.c13
-rw-r--r--drivers/gpu/drm/tegra/gem.h13
-rw-r--r--include/uapi/drm/tegra_drm.h2
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,
window.dst.h = crtc_h;
window.format = tegra_dc_format(fb->pixel_format);
window.bits_per_pixel = fb->bits_per_pixel;
+ window.tiled = tegra_fb_is_tiled(fb);
for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
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,
tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
+ if (tegra_fb_is_tiled(fb)) {
+ value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+ DC_WIN_BUFFER_ADDR_MODE_TILE;
+ } else {
+ value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+ }
+
+ tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+
value = GENERAL_UPDATE | WIN_A_UPDATE;
tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
@@ -509,6 +520,16 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
+ if (window->tiled) {
+ value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+ DC_WIN_BUFFER_ADDR_MODE_TILE;
+ } else {
+ value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+ }
+
+ tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+
value = WIN_ENABLE;
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 @@
#define DC_WIN_BUF_STRIDE 0x70b
#define DC_WIN_UV_BUF_STRIDE 0x70c
#define DC_WIN_BUFFER_ADDR_MODE 0x70d
+#define DC_WIN_BUFFER_ADDR_MODE_LINEAR (0 << 0)
+#define DC_WIN_BUFFER_ADDR_MODE_TILE (1 << 0)
+#define DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV (0 << 16)
+#define DC_WIN_BUFFER_ADDR_MODE_TILE_UV (1 << 16)
#define DC_WIN_DV_CONTROL 0x70e
#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,
struct drm_tegra_gem_create *args = data;
struct tegra_bo *bo;
- bo = tegra_bo_create_with_handle(file, drm, args->size,
+ bo = tegra_bo_create_with_handle(file, drm, args->size, args->flags,
&args->handle);
if (IS_ERR(bo))
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 {
unsigned int format;
unsigned int stride[2];
unsigned long base[3];
+ bool tiled;
};
/* from dc.c */
@@ -254,6 +255,7 @@ extern int tegra_output_exit(struct tegra_output *output);
/* from fb.c */
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
unsigned int index);
+bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
extern int tegra_drm_fb_init(struct drm_device *drm);
extern void tegra_drm_fb_exit(struct drm_device *drm);
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,
return fb->planes[index];
}
+bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
+{
+ struct tegra_fb *fb = to_tegra_fb(framebuffer);
+
+ if (fb->planes[0]->flags & TEGRA_BO_TILED)
+ return true;
+
+ return false;
+}
+
static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
{
struct tegra_fb *fb = to_tegra_fb(framebuffer);
@@ -188,7 +198,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
size = cmd.pitches[0] * cmd.height;
- bo = tegra_bo_create(drm, size);
+ bo = tegra_bo_create(drm, size, 0);
if (IS_ERR(bo))
return PTR_ERR(bo);
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 @@
* GNU General Public License for more details.
*/
+#include <drm/tegra_drm.h>
+
#include "gem.h"
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)
dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr);
}
-struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
+struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
+ unsigned long flags)
{
struct tegra_bo *bo;
int err;
@@ -126,6 +129,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
if (err)
goto err_mmap;
+ if (flags & DRM_TEGRA_GEM_CREATE_TILED)
+ bo->flags |= TEGRA_BO_TILED;
+
return bo;
err_mmap:
@@ -142,12 +148,13 @@ err_dma:
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
struct drm_device *drm,
unsigned int size,
+ unsigned long flags,
unsigned int *handle)
{
struct tegra_bo *bo;
int ret;
- bo = tegra_bo_create(drm, size);
+ bo = tegra_bo_create(drm, size, flags);
if (IS_ERR(bo))
return bo;
@@ -187,7 +194,7 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
if (args->size < args->pitch * args->height)
args->size = args->pitch * args->height;
- bo = tegra_bo_create_with_handle(file, drm, args->size,
+ bo = tegra_bo_create_with_handle(file, drm, args->size, 0,
&args->handle);
if (IS_ERR(bo))
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 @@
#include <drm/drm.h>
#include <drm/drmP.h>
+#define TEGRA_BO_TILED (1 << 0)
+
struct tegra_bo {
struct drm_gem_object gem;
struct host1x_bo base;
+ unsigned long flags;
dma_addr_t paddr;
void *vaddr;
};
@@ -38,11 +41,13 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
extern const struct host1x_bo_ops tegra_bo_ops;
-struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size);
+struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
+ unsigned long flags);
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
- struct drm_device *drm,
- unsigned int size,
- unsigned int *handle);
+ struct drm_device *drm,
+ unsigned int size,
+ unsigned long flags,
+ unsigned int *handle);
void tegra_bo_free_object(struct drm_gem_object *gem);
int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
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 @@
#include <drm/drm.h>
+#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
+
struct drm_tegra_gem_create {
__u64 size;
__u32 flags;