Commit db7fbdfd authored by Thierry Reding's avatar Thierry Reding Committed by Thierry Reding

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: default avatarThierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 773af77f
...@@ -47,6 +47,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -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.bottom_up = tegra_fb_is_bottom_up(fb);
window.tiled = tegra_fb_is_tiled(fb); 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++) {
...@@ -147,6 +148,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, ...@@ -147,6 +148,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
{ {
unsigned int format = tegra_dc_format(fb->pixel_format); unsigned int format = tegra_dc_format(fb->pixel_format);
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
unsigned int h_offset = 0, v_offset = 0;
unsigned long value; unsigned long value;
tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); 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,6 +170,22 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
/* make sure bottom-up buffers are properly displayed */
if (tegra_fb_is_bottom_up(fb)) {
value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
value |= INVERT_V;
tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
v_offset += fb->height - 1;
} else {
value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
value &= ~INVERT_V;
tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
}
tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
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);
...@@ -517,6 +535,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, ...@@ -517,6 +535,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE); tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
} }
if (window->bottom_up)
v_offset += window->src.h - 1;
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);
...@@ -548,6 +569,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, ...@@ -548,6 +569,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
value |= COLOR_EXPAND; value |= COLOR_EXPAND;
} }
if (window->bottom_up)
value |= INVERT_V;
tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
/* /*
......
...@@ -302,6 +302,7 @@ ...@@ -302,6 +302,7 @@
#define DC_WIN_CSC_KVB 0x618 #define DC_WIN_CSC_KVB 0x618
#define DC_WIN_WIN_OPTIONS 0x700 #define DC_WIN_WIN_OPTIONS 0x700
#define INVERT_V (1 << 2)
#define COLOR_EXPAND (1 << 6) #define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18) #define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30) #define WIN_ENABLE (1 << 30)
......
...@@ -148,6 +148,7 @@ struct tegra_dc_window { ...@@ -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 bottom_up;
bool tiled; bool tiled;
}; };
...@@ -255,6 +256,7 @@ extern int tegra_output_exit(struct tegra_output *output); ...@@ -255,6 +256,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_bottom_up(struct drm_framebuffer *framebuffer);
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); 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);
......
...@@ -34,6 +34,16 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, ...@@ -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_bottom_up(struct drm_framebuffer *framebuffer)
{
struct tegra_fb *fb = to_tegra_fb(framebuffer);
if (fb->planes[0]->flags & TEGRA_BO_BOTTOM_UP)
return true;
return false;
}
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
{ {
struct tegra_fb *fb = to_tegra_fb(framebuffer); struct tegra_fb *fb = to_tegra_fb(framebuffer);
......
...@@ -132,6 +132,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, ...@@ -132,6 +132,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
if (flags & DRM_TEGRA_GEM_CREATE_TILED) if (flags & DRM_TEGRA_GEM_CREATE_TILED)
bo->flags |= TEGRA_BO_TILED; bo->flags |= TEGRA_BO_TILED;
if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP)
bo->flags |= TEGRA_BO_BOTTOM_UP;
return bo; return bo;
err_mmap: err_mmap:
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#define TEGRA_BO_TILED (1 << 0) #define TEGRA_BO_TILED (1 << 0)
#define TEGRA_BO_BOTTOM_UP (1 << 1)
struct tegra_bo { struct tegra_bo {
struct drm_gem_object gem; struct drm_gem_object gem;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <drm/drm.h> #include <drm/drm.h>
#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) #define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
struct drm_tegra_gem_create { struct drm_tegra_gem_create {
__u64 size; __u64 size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment