Commit d1f3e1e0 authored by Thierry Reding's avatar Thierry Reding

drm/tegra: Properly align stride for framebuffers

Tegra20 and Tegra30 both required the buffer line stride to be aligned
on 8 byte boundaries. Tegra114 and Tegra124 increased the alignment to
64 bytes. Introduce a parameter to specify the alignment requirements
for each display controller and round up the pitch of newly allocated
framebuffers appropriately.
Originally-by: default avatarStéphane Marchesin <marcheu@chromium.org>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 3f4f3b5f
...@@ -19,6 +19,7 @@ struct tegra_dc_soc_info { ...@@ -19,6 +19,7 @@ struct tegra_dc_soc_info {
bool supports_interlacing; bool supports_interlacing;
bool supports_cursor; bool supports_cursor;
bool supports_block_linear; bool supports_block_linear;
unsigned int pitch_align;
}; };
struct tegra_plane { struct tegra_plane {
...@@ -1283,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client) ...@@ -1283,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client)
{ {
struct drm_device *drm = dev_get_drvdata(client->parent); struct drm_device *drm = dev_get_drvdata(client->parent);
struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_dc *dc = host1x_client_to_dc(client);
struct tegra_drm *tegra = drm->dev_private;
int err; int err;
drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
drm_mode_crtc_set_gamma_size(&dc->base, 256); drm_mode_crtc_set_gamma_size(&dc->base, 256);
drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
/*
* Keep track of the minimum pitch alignment across all display
* controllers.
*/
if (dc->soc->pitch_align > tegra->pitch_align)
tegra->pitch_align = dc->soc->pitch_align;
err = tegra_dc_rgb_init(drm, dc); err = tegra_dc_rgb_init(drm, dc);
if (err < 0 && err != -ENODEV) { if (err < 0 && err != -ENODEV) {
dev_err(dc->dev, "failed to initialize RGB output: %d\n", err); dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
...@@ -1347,18 +1356,28 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { ...@@ -1347,18 +1356,28 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.supports_interlacing = false, .supports_interlacing = false,
.supports_cursor = false, .supports_cursor = false,
.supports_block_linear = false, .supports_block_linear = false,
.pitch_align = 8,
}; };
static const struct tegra_dc_soc_info tegra30_dc_soc_info = { static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.supports_interlacing = false, .supports_interlacing = false,
.supports_cursor = false, .supports_cursor = false,
.supports_block_linear = false, .supports_block_linear = false,
.pitch_align = 8,
};
static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 64,
}; };
static const struct tegra_dc_soc_info tegra124_dc_soc_info = { static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.supports_interlacing = true, .supports_interlacing = true,
.supports_cursor = true, .supports_cursor = true,
.supports_block_linear = true, .supports_block_linear = true,
.pitch_align = 64,
}; };
static const struct of_device_id tegra_dc_of_match[] = { static const struct of_device_id tegra_dc_of_match[] = {
......
...@@ -45,6 +45,8 @@ struct tegra_drm { ...@@ -45,6 +45,8 @@ struct tegra_drm {
#ifdef CONFIG_DRM_TEGRA_FBDEV #ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_fbdev *fbdev; struct tegra_fbdev *fbdev;
#endif #endif
unsigned int pitch_align;
}; };
struct tegra_drm_client; struct tegra_drm_client;
......
...@@ -194,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, ...@@ -194,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes) struct drm_fb_helper_surface_size *sizes)
{ {
struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
struct tegra_drm *tegra = helper->dev->dev_private;
struct drm_device *drm = helper->dev; struct drm_device *drm = helper->dev;
struct drm_mode_fb_cmd2 cmd = { 0 }; struct drm_mode_fb_cmd2 cmd = { 0 };
unsigned int bytes_per_pixel; unsigned int bytes_per_pixel;
...@@ -208,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, ...@@ -208,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
cmd.width = sizes->surface_width; cmd.width = sizes->surface_width;
cmd.height = sizes->surface_height; cmd.height = sizes->surface_height;
cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
tegra->pitch_align);
cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth); sizes->surface_depth);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/dma-buf.h> #include <linux/dma-buf.h>
#include <drm/tegra_drm.h> #include <drm/tegra_drm.h>
#include "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)
...@@ -259,8 +260,10 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, ...@@ -259,8 +260,10 @@ 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)
{ {
int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
struct tegra_drm *tegra = drm->dev_private;
struct tegra_bo *bo; struct tegra_bo *bo;
min_pitch = round_up(min_pitch, tegra->pitch_align);
if (args->pitch < min_pitch) if (args->pitch < min_pitch)
args->pitch = min_pitch; args->pitch = min_pitch;
......
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