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>
This commit is contained in:
Thierry Reding 2013-10-04 22:34:01 +02:00 committed by Thierry Reding
parent 5f60ed0d84
commit 773af77fc4
8 changed files with 60 additions and 9 deletions

View File

@ -47,6 +47,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
window.dst.h = crtc_h; window.dst.h = crtc_h;
window.format = tegra_dc_format(fb->pixel_format); window.format = tegra_dc_format(fb->pixel_format);
window.bits_per_pixel = fb->bits_per_pixel; 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++) { for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
struct tegra_bo *bo = tegra_fb_get_plane(fb, 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, fb->pitches[0], DC_WIN_LINE_STRIDE);
tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); 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; value = GENERAL_UPDATE | WIN_A_UPDATE;
tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); 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, h_offset, DC_WINBUF_ADDR_H_OFFSET);
tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_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; value = WIN_ENABLE;
if (yuv) { if (yuv) {

View File

@ -365,6 +365,10 @@
#define DC_WIN_BUF_STRIDE 0x70b #define DC_WIN_BUF_STRIDE 0x70b
#define DC_WIN_UV_BUF_STRIDE 0x70c #define DC_WIN_UV_BUF_STRIDE 0x70c
#define DC_WIN_BUFFER_ADDR_MODE 0x70d #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_DV_CONTROL 0x70e
#define DC_WIN_BLEND_NOKEY 0x70f #define DC_WIN_BLEND_NOKEY 0x70f

View File

@ -262,7 +262,7 @@ static int tegra_gem_create(struct drm_device *drm, void *data,
struct drm_tegra_gem_create *args = data; struct drm_tegra_gem_create *args = data;
struct tegra_bo *bo; 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); &args->handle);
if (IS_ERR(bo)) if (IS_ERR(bo))
return PTR_ERR(bo); return PTR_ERR(bo);

View File

@ -148,6 +148,7 @@ struct tegra_dc_window {
unsigned int format; unsigned int format;
unsigned int stride[2]; unsigned int stride[2];
unsigned long base[3]; unsigned long base[3];
bool tiled;
}; };
/* from dc.c */ /* from dc.c */
@ -254,6 +255,7 @@ extern int tegra_output_exit(struct tegra_output *output);
/* from fb.c */ /* from fb.c */
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
unsigned int index); unsigned int index);
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
extern int tegra_drm_fb_init(struct drm_device *drm); extern int tegra_drm_fb_init(struct drm_device *drm);
extern void tegra_drm_fb_exit(struct drm_device *drm); extern void tegra_drm_fb_exit(struct drm_device *drm);
extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);

View File

@ -34,6 +34,16 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
return fb->planes[index]; 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) static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
{ {
struct tegra_fb *fb = to_tegra_fb(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; size = cmd.pitches[0] * cmd.height;
bo = tegra_bo_create(drm, size); bo = tegra_bo_create(drm, size, 0);
if (IS_ERR(bo)) if (IS_ERR(bo))
return PTR_ERR(bo); return PTR_ERR(bo);

View File

@ -18,6 +18,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <drm/tegra_drm.h>
#include "gem.h" #include "gem.h"
static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) 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); 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; struct tegra_bo *bo;
int err; int err;
@ -126,6 +129,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
if (err) if (err)
goto err_mmap; goto err_mmap;
if (flags & DRM_TEGRA_GEM_CREATE_TILED)
bo->flags |= TEGRA_BO_TILED;
return bo; return bo;
err_mmap: err_mmap:
@ -142,12 +148,13 @@ err_dma:
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
struct drm_device *drm, struct drm_device *drm,
unsigned int size, unsigned int size,
unsigned long flags,
unsigned int *handle) unsigned int *handle)
{ {
struct tegra_bo *bo; struct tegra_bo *bo;
int ret; int ret;
bo = tegra_bo_create(drm, size); bo = tegra_bo_create(drm, size, flags);
if (IS_ERR(bo)) if (IS_ERR(bo))
return 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) if (args->size < args->pitch * args->height)
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); &args->handle);
if (IS_ERR(bo)) if (IS_ERR(bo))
return PTR_ERR(bo); return PTR_ERR(bo);

View File

@ -24,9 +24,12 @@
#include <drm/drm.h> #include <drm/drm.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#define TEGRA_BO_TILED (1 << 0)
struct tegra_bo { struct tegra_bo {
struct drm_gem_object gem; struct drm_gem_object gem;
struct host1x_bo base; struct host1x_bo base;
unsigned long flags;
dma_addr_t paddr; dma_addr_t paddr;
void *vaddr; 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; 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 tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
struct drm_device *drm, struct drm_device *drm,
unsigned int size, unsigned int size,
unsigned int *handle); unsigned long flags,
unsigned int *handle);
void tegra_bo_free_object(struct drm_gem_object *gem); void tegra_bo_free_object(struct drm_gem_object *gem);
int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
struct drm_mode_create_dumb *args); struct drm_mode_create_dumb *args);

View File

@ -19,6 +19,8 @@
#include <drm/drm.h> #include <drm/drm.h>
#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
struct drm_tegra_gem_create { struct drm_tegra_gem_create {
__u64 size; __u64 size;
__u32 flags; __u32 flags;