Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1f3e1e0 authored by Thierry Reding's avatar Thierry Reding
Browse files

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
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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[] = {
+2 −0
Original line number Diff line number Diff line
@@ -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;
+3 −1
Original line number Diff line number Diff line
@@ -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);

+3 −0
Original line number Diff line number Diff line
@@ -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;