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.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) {

View File

@ -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

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 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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,10 +41,12 @@ 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 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,

View File

@ -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;