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:
parent
5f60ed0d84
commit
773af77fc4
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue