mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 15:13:52 +00:00
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: Stéphane Marchesin <marcheu@chromium.org> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
3f4f3b5fed
commit
d1f3e1e0b3
@ -19,6 +19,7 @@ struct tegra_dc_soc_info {
|
||||
bool supports_interlacing;
|
||||
bool supports_cursor;
|
||||
bool supports_block_linear;
|
||||
unsigned int pitch_align;
|
||||
};
|
||||
|
||||
struct tegra_plane {
|
||||
@ -1283,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(client->parent);
|
||||
struct tegra_dc *dc = host1x_client_to_dc(client);
|
||||
struct tegra_drm *tegra = drm->dev_private;
|
||||
int err;
|
||||
|
||||
drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
|
||||
drm_mode_crtc_set_gamma_size(&dc->base, 256);
|
||||
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);
|
||||
if (err < 0 && err != -ENODEV) {
|
||||
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 = {
|
||||
.supports_interlacing = false,
|
||||
.supports_cursor = false,
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 8,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
|
||||
.supports_interlacing = false,
|
||||
.supports_cursor = 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 = {
|
||||
.supports_interlacing = true,
|
||||
.supports_cursor = true,
|
||||
.supports_block_linear = true,
|
||||
.pitch_align = 64,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_dc_of_match[] = {
|
||||
|
@ -45,6 +45,8 @@ struct tegra_drm {
|
||||
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||
struct tegra_fbdev *fbdev;
|
||||
#endif
|
||||
|
||||
unsigned int pitch_align;
|
||||
};
|
||||
|
||||
struct tegra_drm_client;
|
||||
|
@ -194,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
|
||||
struct tegra_drm *tegra = helper->dev->dev_private;
|
||||
struct drm_device *drm = helper->dev;
|
||||
struct drm_mode_fb_cmd2 cmd = { 0 };
|
||||
unsigned int bytes_per_pixel;
|
||||
@ -208,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
|
||||
|
||||
cmd.width = sizes->surface_width;
|
||||
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,
|
||||
sizes->surface_depth);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm/tegra_drm.h>
|
||||
|
||||
#include "drm.h"
|
||||
#include "gem.h"
|
||||
|
||||
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,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
|
||||
struct tegra_drm *tegra = drm->dev_private;
|
||||
struct tegra_bo *bo;
|
||||
|
||||
min_pitch = round_up(min_pitch, tegra->pitch_align);
|
||||
if (args->pitch < min_pitch)
|
||||
args->pitch = min_pitch;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user